【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 }
没有什么不可能。