题目描述
一天Blinker醒来,发现自己成为了一个二维世界的点,而且被标记上了一个奇怪的值。 这个世界是由N个边界互不相交(且不相切)的图形组成,这里图形仅包括圆和凸多边形。每个图形还有一个权值。每次Blinker走进或走出某个图形时(相切时经过不算),Blinker的标记值就会被异或上那个值。 现在,我们记录了Blinker在这个世界的M天的信息。每天可能发生两种事情,一种是某个图形的权值更改为某个值;另一种是Blinker从某个点走到另一个点。 我们假设Blinker首次出发前的标记值为0,我们希望知道他每次到达目的地后的标记
值。
输入格式
输入的第一行包含2个数,N和M,分别表示这个世界的图形数和记录的天数。 接下来有N行,每行表示一个图形。 如果一行以字符C开头,表示这个图形是一个圆,后面紧跟着三个实数x, y, r和一个整数v,分别表示圆的x坐标,y坐标和圆的半径以及该图形对应的值。 如果一行以字符P开头,表示这个图形是凸多边形,后面紧跟着一个整数L,表示凸多
边形的点数,然后后面有L对实数x0,y0,x1,y1…,表示L个点的坐标,这一行最后一个数是一个整数v,表示这个图形对应的值,保证凸多边形上的点按照顺时针给出。 接下来有M行,每行表示一天的记录信息。
如果一行以字符Q开头,表示这一天Blinker出行了,接下来有x0,y0,x1,y1四个实数,分别表示出发点的坐标和目的地的坐标。
如果一行以字符C开头,表示这一天某个图形的值改变了,接下来有两个i 和v,表示输入中第i 个出现的图形的值变成v。
输出格式
对于Blinker的每个出行输出他到达目的地后的标记值,很显然这个值与Blinker的路径无关。
提示
1<=N<=100000,1<=M<=100000,单个凸多边形的点数小于等于34。图形互不相交,且Blinker的出发点和目的地不在图形的边界。
-
- 由于只有包含和相离所以是一个树形结构,只需要找到每个图形的父亲建树;
- 询问即树链上的异或和,BIT维护即可;
- 将每个多边形分成上壳和下壳;
- 按$x$坐标扫描,图不相交,有个性质:一旦加入图形的上下关系就是确定的,$splay$维护$y$坐标的大小;
- 查询$(x,y)$可以直接在扫描到$x$的时候查找$y$的前驱,如果是下壳则就是查到的图形,否则是它的父亲;
- 点定位和图形定位都是这个思路;
- 我看的Claris的题解,自己写了,改了两天一直只有30,又不会造数据,不得已只能照着代码改成和$std$要像不像的才过了。。。。TAT
- 至今不知道自己错哪里了。。。。
#include<bits/stdc++.h> #define ld double using namespace std; const int N=100010; const ld inf=1e20,eps=1e-9; int n,m,cnt,tot,o=1,hd[N],f[N],st[N],ed[N],idx,c[N],rt,ch[N<<1][2],fa[N<<1],bl[N<<1]; ld X; struct Edge{int v,nt;}E[N<<1]; char s[10]; struct P{ ld x,y; P(ld _x=0,ld _y=0):x(_x),y(_y){}; bool operator <(const P&a)const{return x==a.x?y<a.y:x<a.x;} }q[N<<1]; struct line{ld x;int id,typ;}B[N<<2]; struct Graph{ int typ,w; int n;P p[35]; P O;ld R; void init(){ scanf("%s",s+1); typ=s[1]=='P'; if(!typ)scanf("%lf%lf%lf%d",&O.x,&O.y,&R,&w); else{ scanf("%d",&n); for(int j=0;j<n;++j)scanf("%lf%lf",&p[j].x,&p[j].y); scanf("%d",&w); p[n]=p[0]; } } ld getl(){ if(!typ)return O.x-R; ld re=inf; for(int i=0;i<n;++i)re=min(re,p[i].x); return re; } ld getr(){ if(!typ)return O.x+R; ld re=-inf; for(int i=0;i<n;++i)re=max(re,p[i].x); return re; } ld cal0(ld x){ if(!typ)return O.y+sqrt(max(R*R-(x-O.x)*(x-O.x),0.0)); ld re=-inf; for(int i=0;i<n;++i){ ld A=p[i].x,B=p[i].y,C=p[i+1].x,D=p[i+1].y; if(A>C)swap(A,C),swap(B,D); if(x<A-eps||x>C+eps)continue; if(x<A+eps){re=max(re,B);continue;} if(x>C-eps){re=max(re,D);continue;} re=max(re,B+(D-B)/(C-A)*(x-A)); } return re; } ld cal1(ld x){ if(!typ)return O.y-sqrt(max(R*R-(x-O.x)*(x-O.x),0.0)); ld re=inf; for(int i=0;i<n;++i){ ld A=p[i].x,B=p[i].y,C=p[i+1].x,D=p[i+1].y; if(A>C)swap(A,C),swap(B,D); if(x<A-eps||x>C+eps)continue; if(x<A+eps){re=min(re,B);continue;} if(x>C-eps){re=min(re,D);continue;} re=min(re,B+(D-B)/(C-A)*(x-A)); } return re; } }A[N]; struct Query{int typ,u,v,x;}C[N]; bool cmpB(const line&a,const line&b){ if(a.typ&&b.typ&&a.id==b.id)return a.typ>b.typ; return a.x<b.x; } bool cmp1(int k,ld y){ if(k==(n<<1|1))return 1; if(k==(n<<1))return 0; ld t=k&1?A[k>>1].cal1(X):A[k>>1].cal0(X); return t<y; } bool cmp2(int x,int y){ if(x==(n<<1|1))return 1; if(x==(n<<1))return 0; if((x^y)==1)return x&1; ld t1=x&1?A[x>>1].cal1(X):A[x>>1].cal0(X), t2=y&1?A[y>>1].cal1(X):A[y>>1].cal0(X); return t1<t2; } void rotate(int x,int&k){ int y=fa[x],z=fa[y]; if(y!=k)ch[z][ch[z][1]==y]=x;else k=x; int l=ch[y][1]==x,r=l^1; fa[x]=z;fa[y]=x;fa[ch[x][r]]=y; ch[y][l]=ch[x][r],ch[x][r]=y; } void splay(int x,int&k){ for(int y,z;x!=k;rotate(x,k)){ y=fa[x],z=fa[y]; if(y!=k)rotate((ch[z][1]==y)^(ch[y][1]==x) ? x : y , k); } } void adde(int u,int v){ E[o]=(Edge){v,hd[u]}; f[v]=u;hd[u]=o++; } void ins(int&k,int x){ if(!k){k=x;return;} int d=cmp2(k,x); ins(ch[k][d],x); fa[ch[k][d]]=k; } int find(ld y){ int k=rt,re=0; while(k){ if(cmp1(k,y))re=k,k=ch[k][1]; else k=ch[k][0]; }return re; } void add(int x){ /*if(x==20193){ puts("haha"); }*/ int p=x<<1,q=p|1; ins(rt,p);ins(rt,q); splay(q,rt); int t=ch[q][0]; while(ch[t][1])t=ch[t][1]; adde(t&1?t>>1:f[t>>1],x); splay(t,rt); } void del(int x){ splay(x,rt); int y=ch[x][0]; while(ch[y][1])y=ch[y][1]; splay(y,ch[x][0]); ch[y][1]=ch[x][1]; fa[ch[x][1]]=y; fa[rt=y]=0; } void getp(int x){ int t=find(q[x].y); bl[x]=t&1?t>>1:f[t>>1]; splay(t,rt); } void mfy(int x,int y){for(;x<=n;x+=x&-x)c[x]^=y;} int ask(int x){int re=0;for(;x;x-=x&-x)re^=c[x];return re;} void upd(int x,int y){ swap(y,A[x].w);y^=A[x].w; mfy(st[x],y);mfy(ed[x]+1,y); } int que(int x){return ask(st[x]);} void dfs(int u){ st[u]=++idx; mfy(st[u],A[u].w); for(int i=hd[u];i;i=E[i].nt)dfs(E[i].v); ed[u]=idx; mfy(ed[u]+1,A[u].w); } int main(){ #ifndef ONLINE_JUDGE freopen("T3.in","r",stdin); freopen("T3.out","w",stdout); #endif scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ A[i].init(); B[++cnt]=(line){A[i].getl(),i,1}; B[++cnt]=(line){A[i].getr(),i,-1}; } for(int i=1;i<=m;++i){ scanf("%s",s+1); C[i].typ=s[1]=='Q'; if(!C[i].typ)scanf("%d%d",&C[i].u,&C[i].x); else{ C[i].u=++tot,scanf("%lf%lf",&q[tot].x,&q[tot].y); B[++cnt]=(line){q[tot].x,tot,0}; C[i].v=++tot,scanf("%lf%lf",&q[tot].x,&q[tot].y); B[++cnt]=(line){q[tot].x,tot,0}; } } sort(B+1,B+cnt+1,cmpB); ++n; ch[rt=n<<1][0]=n<<1|1; fa[n<<1|1]=n<<1; for(int i=1;i<=cnt;++i){ X=B[i].x; if(B[i].typ==1)add(B[i].id); else if(B[i].typ==-1)del(B[i].id<<1),del(B[i].id<<1|1); else getp(B[i].id); } dfs(n); int ans=0; for(int i=1;i<=m;++i)if(C[i].typ){ ans^=que(bl[C[i].u])^que(bl[C[i].v]); printf("%d\n",ans); }else upd(C[i].u,C[i].x); return 0; }