luogu2542 航线规划 (树链剖分)
Posted ressed
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu2542 航线规划 (树链剖分)相关的知识,希望对你有一定的参考价值。
不会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 ",ans[i]); 137 return 0; 138 }
以上是关于luogu2542 航线规划 (树链剖分)的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1969: [Ahoi2005]LANE 航线规划( 树链剖分 )
BZOJ1969[Ahoi2005]LANE 航线规划 离线+树链剖分+线段树
bzoj1969 [Ahoi2005]LANE 航线规划 树链剖分