【BZOJ】1969: [Ahoi2005]LANE 航线规划

题目链接:

  传送~~

题解:

    老夫实在是码不动了……

  正着搞显然不好做,尝试倒着乱搞。先给被删除的边标记一个时间戳,先删除的时间戳大,同时维护询问时间戳,询问早的时间戳大。没被删除过的边时间戳都是0。然后瞎tarjan一次,建立双联通分量树。然后考虑每条被删除的边补会图中,相当于把两点所属双联通分量之间路径边权变为0。然后强行树剖一波即可。

  (调死人啦!

代码:

 

  1 #define Troy 10/19/2017
  2 
  3 #include <bits/stdc++.h>
  4 
  5 using namespace std;
  6 
  7 inline int read(){
  8     int s=0,k=1;char ch=getchar();
  9     while(ch<'0'|ch>'9')    ch=='-'?k=-1:0,ch=getchar();
 10     while(ch>47&ch<='9')    s=s*10+(ch^48),ch=getchar();
 11     return s*k;
 12 }
 13 
 14 const int N=1e5+8;
 15 
 16 int n,m,q,ans[N];
 17 
 18 struct Q{
 19     int u,v,times,val;
 20     inline void in(){
 21         u=read(),v=read(),val=0;
 22         if(u>v)    swap(u,v);
 23     }
 24 }query[N<<1];
 25 
 26 inline bool cmpx(Q a,Q b){
 27     return a.u!=b.u?a.u<b.u:a.v<b.v;
 28 }
 29 
 30 inline bool cmpy(Q a,Q b){
 31     return a.times<b.times;
 32 }
 33 
 34 struct edges{ 
 35     int v;edges *last;
 36 }edge[N<<2],*head[N];int cnt;
 37 
 38 inline void push(int u,int v){
 39     edge[++cnt]=(edges){v,head[u]};head[u]=edge+cnt;
 40 }
 41 
 42 /**********************************************************************/
 43 
 44 int dfn[N],low[N],bccno[N],idx,stk[N],top,bcc_cnt;
 45 
 46 inline void tarjan(int x,int fa){
 47     dfn[x]=low[x]=++idx;
 48     stk[++top]=x;
 49     for(edges *i=head[x];i;i=i->last)    if(i->v!=fa){
 50         if(!dfn[i->v]){
 51             tarjan(i->v,x);
 52             low[x]=min(low[x],low[i->v]);
 53         }else
 54             low[x]=min(low[x],dfn[i->v]);
 55     }
 56     if(dfn[fa]<low[x]){
 57         bcc_cnt++;int t;
 58         do{
 59             t=stk[top--];
 60             bccno[t]=bcc_cnt;
 61         }while(t!=x);
 62     }
 63 }
 64 
 65 /*****************************************************************/
 66 int size[N],heavy[N],deep[N],g[N],f[N],tid[N];
 67 
 68 inline void dfs(int x,int fa){
 69     size[x]=1;
 70     for(edges *i=head[x];i;i=i->last)if(i->v!=fa){
 71         deep[i->v]=deep[x]+1;
 72         f[i->v]=x;
 73         dfs(i->v,x);
 74         size[x]+=size[i->v];
 75         if(size[i->v]>size[heavy[x]])
 76             heavy[x]=i->v;
 77     }
 78 }
 79 
 80 inline void dfs(int x,int fa,int grand){
 81     tid[x]=++idx;
 82     g[x]=grand;
 83     if(heavy[x])
 84         dfs(heavy[x],x,grand);
 85     for(edges *i=head[x];i;i=i->last)
 86         if(i->v!=fa&&i->v!=heavy[x])
 87             dfs(i->v,x,i->v);
 88 }
 89 
 90 inline void init(){
 91     n=read(),m=read();
 92     for(int i=1;i<=m;i++)
 93         query[i].in();
 94     sort(query+1,query+1+m,cmpx);
 95     int t=1e6;
 96     while(1){
 97         int c=read(),a,b;
 98         if(c==-1)    break;
 99         a=read(),b=read();
100         if(a>b)    swap(a,b);
101         if(c==0){
102             int x=upper_bound(query+1,query+1+m,(Q){a,b,0,0},cmpx)-query-1;
103             query[x].times=t;
104         }else{
105             q++;
106             query[q+m]=(Q){a,b,t,1};
107         }
108         t--;
109     }
110     sort(query+1,query+1+q+m,cmpy);
111     for(int i=1;i<=m+q&&query[i].times==0;i++)
112         push(query[i].u,query[i].v),
113         push(query[i].v,query[i].u);
114     tarjan(1,0);
115     memset(head,0,sizeof(head));cnt=0;
116     for(int i=1;i<=m+q&&query[i].times==0;i++)
117         if(bccno[query[i].u]!=bccno[query[i].v])
118             push(bccno[query[i].u],bccno[query[i].v]),
119             push(bccno[query[i].v],bccno[query[i].u]);    
120     dfs(1,1);    
121     idx=0;
122     dfs(1,1,1);
123 }
124 
125 /********************************************************************/
126 
127 struct Tree{
128     Tree *son[2];
129     int val;
130 }*root,tree[N<<2];int t_cnt;
131 
132 inline void build(Tree *&u,int l,int r){
133     u=tree+t_cnt;t_cnt++;
134     u->val=0;
135     if(l==r){
136         u->son[0]=u->son[1]=NULL;
137         u->val=(l!=1);
138         return;
139     }
140     int mid=l+r>>1;
141     build(u->son[0],l,mid);
142     build(u->son[1],mid+1,r);
143     for(int i=0;i<2;i++)
144         u->val+=u->son[i]->val;
145 }
146 
147 inline void change(Tree *u,int l,int r,int x,int y){
148     if((x<=l&&r<=y)||u->val==0){    
149         u->val=0;
150         return;
151     }
152     int mid=l+r>>1;
153     if(y>mid)
154         change(u->son[1],mid+1,r,x,y);
155     if(x<=mid)
156         change(u->son[0],l,mid,x,y);
157     u->val=0;
158     for(int i=0;i<2;i++)
159         u->val+=u->son[i]->val;
160 }
161 
162 inline int sum(Tree *u,int l,int r,int x,int y){
163     if(u->val==0)    return 0;    
164     if(x<=l&&r<=y)
165         return u->val;
166     int mid=l+r>>1;
167     if(x>mid)
168         return sum(u->son[1],mid+1,r,x,y);
169     else    if(y<=mid)
170         return sum(u->son[0],l,mid,x,y);
171     else    return sum(u->son[0],l,mid,x,y)+sum(u->son[1],mid+1,r,x,y);
172 }
173 
174 inline void change(int x,int y){
175     while(g[x]!=g[y]){
176         if(deep[g[x]]<deep[g[y]])
177             swap(x,y);
178         change(root,1,idx,tid[g[x]],tid[x]);        
179         x=f[g[x]];
180     }
181     if(x==y)    return;
182     if(deep[x]>deep[y])
183         swap(x,y);
184     change(root,1,idx,tid[x]+1,tid[y]);
185 }
186 
187 inline int sum(int x,int y){
188     int ret=0;
189     while(g[x]!=g[y]){
190         if(deep[g[x]]<deep[g[y]])
191             swap(x,y);
192         ret+=sum(root,1,idx,tid[g[x]],tid[x]);
193         x=f[g[x]];
194     }
195     if(x!=y){
196         if(deep[x]>deep[y])
197             swap(x,y);
198         ret+=sum(root,1,idx,tid[x]+1,tid[y]);
199     }
200     return ret;
201 }
202 
203 inline void work(){
204     build(root,1,idx);
205     int t=q;
206     for(int i=1;i<=m+q;i++)
207         if(query[i].times==0)
208             continue;
209         else{
210             if(query[i].val==0){
211                 change(bccno[query[i].u],bccno[query[i].v]);
212             }
213             else{
214                 ans[t]=sum(bccno[query[i].u],bccno[query[i].v]);
215                 t--;
216             }
217         }
218     for(int i=1;i<=q;i++)
219         printf("%d\n",ans[i]);
220 }
221 
222 int main(){
223     init();
224     work();
225 }

 

posted @ 2017-10-20 18:43  Troywar  阅读(278)  评论(0编辑  收藏  举报