[BZOJ2758] [SCOI2012]Blinker的噩梦 扫描线+set
题目大意:有n个圆或凸多边形,这些图形不会相交,每当走入或走出一个图形时需要异或上一个代价,有m组操作:
询问操作,每次询问从一个点走到另一个点时,需要的代价(初始代价为0)
修改操作,每次修改一个图形的代价
数据范围:n≤1e5,点权的绝对值不大于1e9
此题真实毒瘤题
考虑到此题图形之间两两互不相交,那么图形与图形之间的关系为相离或包含,包含关系我们可以将其建成一棵树结构。
我们用set来维护一个以x为第一关键字的扫描线,每次扫描到一个新的图形,我们就将该图形拆成上下两部分(可以理解为左右括号),分别加入到set中(考虑到图形不会包含,那么在图形出现的值域内,如果只考虑当前加入的这些图形,这些图形构成的括号序列是不会发生变化的,我们只需要写一个在给定X值情况下能求出图形上下两部分的Y值的函数即可)
然后再做一条射线往上,碰到了另一个多边形,不难发现只会有两种情况:
第一种情况:遇到一个图形的上部分,那么显然碰到的那个图形包含了当前图形。
第二种情况:遇到一个图形的下部分,那么显然当前图形与碰到的图形是相离关系。
当某个图形在扫描线变化后不再出现时,从set中删去这个图形。
(以上说得有点玄乎,感性理解下吧)
我们基于这些关系,建出了一棵树。
对于一个查询操作,显然是查询从树上一个点到另一个点的异或和,考虑到这个值可能会被修改,用树状数组随便维护下就好了
然后就没了,说起来很简单写起来hhh。
注意精度损失!!!!!
1 #include<bits/stdc++.h> 2 #define M 300005 3 #define INF 1e15 4 #define eps 1e-9 5 #define D long double 6 #define sqr(x) ((x)*(x)) 7 #define lowbit(x) ((x)&(-x)) 8 using namespace std; 9 10 int b[M]={0},N,val[M]={0}; 11 void updata(int x,int k){ for(int i=x;i<=N;i+=lowbit(i)) b[i]^=k;} 12 int query(int x){ int k=0; for(int i=x;i;i-=lowbit(i)) k^=b[i]; return k;} 13 14 struct edge{int u,next;}e[M]={0}; int head[M]={0},use=0; 15 void add(int x,int y){use++;e[use].u=y;e[use].next=head[x];head[x]=use;} 16 int dfn[M]={0},low[M]={0},fa[M]={0},t=0; 17 void dfs(int x){ 18 dfn[x]=++t; 19 for(int i=head[x];i;i=e[i].next) dfs(e[i].u); 20 low[x]=t; 21 updata(dfn[x],val[x]); 22 updata(low[x]+1,val[x]); 23 } 24 25 D nowX; 26 27 struct node{ 28 int n,down,val,id; 29 D X,Y,r,x[37],y[37]; 30 D lx,rx; 31 void makebig(){X=Y=0; r=INF;lx=-INF; rx=INF;} 32 void rd(int ID){ 33 id=ID; 34 char op[10]; scanf("%s",op); 35 if(op[0]=='C'){ 36 n=0; scanf("%Lf%Lf%Lf",&X,&Y,&r); 37 lx=X-r; rx=X+r; 38 }else{ 39 scanf("%d",&n); 40 lx=INF; rx=-INF; 41 for(int i=1;i<=n;i++){ 42 scanf("%Lf%Lf",x+i,y+i); 43 lx=min(lx,x[i]); 44 rx=max(rx,x[i]); 45 } 46 x[n+1]=x[1]; y[n+1]=y[1]; 47 } 48 scanf("%d",&val); 49 } 50 void rd(){ 51 n=-1; 52 scanf("%Lf%Lf",&X,&Y); 53 lx=rx=X; 54 } 55 D get(D now){ 56 D Y1=INF,Y2=-INF; 57 if(n==-1) return Y; 58 if(n==0){ 59 Y1=Y-sqrt(max(sqr(r)-sqr(X-now),(D)0.0)); 60 Y2=Y+sqrt(max(sqr(r)-sqr(X-now),(D)0.0)); 61 }else{ 62 for(int i=1;i<=n;i++){ 63 D now1=x[i],now2=x[i+1]; 64 if(now1==now2) continue; 65 if(now1>now2) swap(now1,now2); 66 if(!(now1-eps<=now&&now<=now2+eps)) continue; 67 D k=(y[i+1]-y[i])/(x[i+1]-x[i]); 68 D nowy=y[i]+(now-x[i])*k; 69 Y1=min(Y1,nowy); 70 Y2=max(Y2,nowy); 71 } 72 } 73 if(down) return Y1; 74 return Y2; 75 } 76 friend bool operator <(node a,node b){ 77 D vala=a.get(nowX); 78 D valb=b.get(nowX); 79 if(fabs(vala-valb)>eps) return vala<valb; 80 return a.down>b.down; 81 } 82 }a[M]; 83 set<node> s; 84 int n,m,q; 85 86 void pushset(node now){ 87 now.down=0; s.insert(now); 88 now.down=1; s.insert(now); 89 } 90 void popset(node now){ 91 now.down=0; s.erase(now); 92 now.down=1; s.erase(now); 93 } 94 95 struct hh{ 96 int id,zf; hh(int ID=0,int ZF=0){id=ID; zf=ZF;} 97 friend bool operator <(hh x,hh y){ 98 D valx,valy; 99 if(x.zf==-1) valx=a[x.id].lx; else valx=a[x.id].rx; 100 if(y.zf==-1) valy=a[y.id].lx; else valy=a[y.id].rx; 101 return valx<valy; 102 } 103 }p[M*3]={0}; 104 105 int pointsum=0; 106 int chx[M]={0},chval[M]={0},id1[M]={0},id2[M]={0}; 107 108 int main(){ 109 // freopen("in.txt","r",stdin); 110 // freopen("out.txt","w",stdout); 111 a[0].makebig(); fa[0]=-1; 112 nowX=-INF; pushset(a[0]); 113 scanf("%d%d",&n,&q); 114 for(int i=1;i<=n;i++) a[++pointsum].rd(i); 115 116 for(int i=1;i<=n;i++) val[i]=a[i].val; 117 for(int i=1;i<=n;i++) p[++m]=hh(i,1),p[++m]=hh(i,-1); 118 119 for(int i=1;i<=q;i++){ 120 char op[10]; scanf("%s",op); 121 if(op[0]=='C'){scanf("%d%d",chx+i,chval+i);} 122 else{ 123 a[++pointsum].rd(); 124 p[++m]=hh(pointsum,0); 125 id1[i]=pointsum; 126 127 a[++pointsum].rd(); 128 p[++m]=hh(pointsum,0); 129 id2[i]=pointsum; 130 } 131 } 132 133 sort(p+1,p+m+1); 134 N=m+1; 135 for(int x=1;x<=m;x++){ 136 int id=p[x].id; 137 //cout<<s.size()<<endl; 138 if(p[x].zf==-1) nowX=a[id].lx; else nowX=a[id].rx; 139 if(p[x].zf==-1||p[x].zf==0){ 140 pushset(a[id]); 141 set<node>::iterator it=s.find(a[id]); it++; 142 if(it->down) 143 fa[id]=fa[it->id]; 144 else fa[id]=it->id; 145 146 if(p[x].zf==0) 147 popset(a[id]); 148 }else{ 149 popset(a[id]); 150 } 151 } 152 for(int i=1;i<=m;i++) add(fa[i],i); 153 dfs(0); 154 int ans=0; 155 for(int i=1;i<=q;i++){ 156 // if(chx[i]) continue; 157 if(chx[i]){ 158 int x=chx[i],zhi=chval[i]; 159 updata(dfn[x],val[x]); 160 updata(low[x]+1,val[x]); 161 val[x]=zhi; 162 updata(dfn[x],val[x]); 163 updata(low[x]+1,val[x]); 164 }else{ 165 int ans1=query(dfn[id1[i]]); 166 int ans2=query(dfn[id2[i]]); 167 ans=ans^ans1^ans2; 168 printf("%d\n",ans); 169 } 170 } 171 // return 0; 172 }