1. 程式人生 > >luogu2542 航線規劃 (樹鏈剖分)

luogu2542 航線規劃 (樹鏈剖分)

pushd style upd truct down 這樣的 print 距離 都是

不會lct,所以只能樹剖亂搞

一般這種刪邊的題都是離線倒著做,變成加邊

他要求的結果其實就是縮點以後兩點間的距離。

然後先根據最後剩下的邊隨便做出一個生成樹,然後假裝把剩下的邊當成加邊操作以後處理

這樣的話,就可以做樹剖來維護現在的兩點間距離。

然後考慮加邊,其實就是加了一條邊然後某一處成環了,縮成了一個點。

這樣的話,就可以把這條邊兩個端點間的距離都改成0,假裝縮了點。

最後再倒著輸出答案就行了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5
#include<queue> 6 #include<map> 7 #include<cmath> 8 #define inf 0x3f3f3f3f 9 #define LL long long int 10 using namespace std; 11 const int maxn=30030,maxm=100010,maxq=40040; 12 13 inline LL rd(){ 14 LL x=0;char c=getchar();int neg=1; 15 while(c<0||c>9){if(c==-
) neg=-1;c=getchar();} 16 while(c>=0&&c<=9) x=x*10+c-0,c=getchar(); 17 return x*neg; 18 } 19 20 struct Edge{ 21 int a,b,ne;bool used,flag; 22 }eg[maxm*2]; 23 int N,M; 24 int egh[maxn],ect; 25 int que[maxq][3],ans[maxq],qct; 26 int fa[maxn],dep[maxn],wson[maxn],siz[maxn],top[maxn],root[maxn],len[maxn];
27 int ch[maxn*4][2],val[maxn*4],pct; 28 bool laz[maxn*4]; 29 map<int,int> mp; 30 31 inline void adeg(int a,int b){ 32 eg[ect].a=a;eg[ect].b=b;eg[ect].ne=egh[a];eg[ect].used=1;egh[a]=ect++; 33 } 34 35 inline void pushdown(int p){ 36 if(!laz[p]) return; 37 val[ch[p][0]]=val[ch[p][1]]=laz[p]=0; 38 laz[ch[p][0]]=laz[ch[p][1]]=1; 39 } 40 inline void update(int p){pushdown(p);val[p]=val[ch[p][0]]+val[ch[p][1]];} 41 42 void build(int &p,int l,int r){ 43 p=++pct; 44 if(l==r) val[p]=1; 45 else{ 46 int m=l+r>>1; 47 build(ch[p][0],l,m);build(ch[p][1],m+1,r); 48 update(p); 49 } 50 } 51 52 int query(int p,int l,int r,int x,int y){ 53 if(x<=l&&r<=y) return val[p]; 54 else{ 55 pushdown(p);int m=l+r>>1,re=0; 56 if(x<=m) re+=query(ch[p][0],l,m,x,y); 57 if(y>=m+1) re+=query(ch[p][1],m+1,r,x,y); 58 return re; 59 } 60 } 61 62 void change(int p,int l,int r,int x,int y){ 63 if(x<=l&&r<=y){ 64 val[p]=0;laz[p]=1;pushdown(p); 65 }else if(val[p]!=0){ 66 pushdown(p);int m=l+r>>1; 67 if(x<=m) change(ch[p][0],l,m,x,y); 68 if(y>=m+1) change(ch[p][1],m+1,r,x,y); 69 update(p); 70 } 71 } 72 73 void dfs1(int x){ 74 siz[x]=1;int ma=0; 75 for(int i=egh[x];i!=-1;i=eg[i].ne){ 76 int b=eg[i].b; 77 if(!eg[i].used||dep[b]) continue; 78 eg[i].flag=eg[i^1].flag=1; 79 fa[b]=x;dep[b]=dep[x]+1; 80 dfs1(b);siz[x]+=siz[b]; 81 if(siz[b]>ma) ma=siz[b],wson[x]=b; 82 } 83 } 84 85 void dfs2(int x){ 86 if(x!=wson[fa[x]]){int d=0; 87 for(int i=x;i;i=wson[i]) top[i]=x,d++; 88 build(root[x],1,d);len[x]=d; 89 }for(int i=egh[x];i!=-1;i=eg[i].ne){ 90 int b=eg[i].b; 91 if(eg[i].flag&&fa[x]!=b) dfs2(b); 92 } 93 } 94 95 void solveC(int x,int y){ 96 while(top[x]!=top[y]){ 97 if(dep[top[x]]<dep[top[y]]) swap(x,y); 98 change(root[top[x]],1,len[top[x]],1,dep[x]-dep[top[x]]+1);x=fa[top[x]]; 99 }if(x==y) return; 100 if(dep[x]>dep[y]) swap(x,y); 101 change(root[top[x]],1,len[top[x]],dep[x]-dep[top[x]]+2,dep[y]-dep[top[y]]+1); 102 } 103 int solveQ(int x,int y){ 104 int re=0; 105 while(top[x]!=top[y]){ 106 107 if(dep[top[x]]<dep[top[y]]) swap(x,y); 108 re+=query(root[top[x]],1,len[top[x]],1,dep[x]-dep[top[x]]+1);x=fa[top[x]]; 109 }if(x==y) return re; 110 if(dep[x]>dep[y]) swap(x,y); 111 return re+query(root[top[x]],1,len[top[x]],dep[x]-dep[top[x]]+2,dep[y]-dep[top[y]]+1); 112 } 113 114 int main(){ 115 int i,j,k; 116 N=rd();M=rd();memset(egh,-1,sizeof(egh)); 117 for(i=1;i<=M;i++){ 118 int a=rd(),b=rd(); 119 mp[a*N+b]=ect;adeg(a,b); 120 mp[b*N+a]=ect;adeg(b,a); 121 }while(++qct){ 122 int a=rd();if(a==-1) break; 123 int b=rd(),c=rd(); 124 que[qct][0]=a;que[qct][1]=b;que[qct][2]=c; 125 if(!a){ 126 int x=mp[b*N+c]; 127 eg[x].used=eg[x^1].used=0; 128 } 129 }dep[1]=1;dfs1(1);dfs2(1); 130 for(i=0;i<ect;i++){ 131 if((!eg[i].flag)&&eg[i].used) solveC(eg[i].a,eg[i].b); 132 }int act=0; 133 for(i=qct-1;i;i--){ 134 if(!que[i][0]) solveC(que[i][1],que[i][2]); 135 else ans[++act]=solveQ(que[i][1],que[i][2]); 136 }for(i=act;i;i--) printf("%d\n",ans[i]); 137 return 0; 138 }

luogu2542 航線規劃 (樹鏈剖分)