[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
",ans);
169         }
170     }
171 //    return 0;
172 }
原文地址:https://www.cnblogs.com/xiefengze1/p/10358489.html