搞了一上午LCT,真是累死了……
以前总觉得LCT高大上不好学不好打,今天打了几遍感觉还可以嘛= =反正现在的水平应付不太难的LCT题也够用了,就这样好了,接下来专心搞网络流。
话说以前一直YY不出来LCT怎么维护边权,多谢sxysxy告诉我要添虚点来把边权转化为点权,感激不尽……
言归正传。
LCT模板题嘛……
区间乘和区间加一遍写对,感觉费了好多rp……
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x))) 6 #define dir(x) ((x)==(x)->p->ch[1]) 7 using namespace std; 8 typedef unsigned uint; 9 const int maxn=100010; 10 const uint M=51061u; 11 struct node{ 12 uint data,sm,a,b; 13 int size; 14 node *ch[2],*p; 15 bool rev; 16 node(uint d=0u):data(d),sm(d),a(1u),b(0u),size(1),rev(false){} 17 void add(uint d){ 18 sm+=(uint)size%M*d%M;sm%=M; 19 data+=d;data%=M; 20 b+=d;b%=M; 21 } 22 void mul(uint d){ 23 sm*=d;sm%=M; 24 data*=d;data%=M; 25 b*=d;b%=M; 26 a*=d;a%=M; 27 } 28 void pushdown(){ 29 if(rev){ 30 ch[0]->rev^=true; 31 ch[1]->rev^=true; 32 swap(ch[0],ch[1]); 33 rev=false; 34 } 35 if(a!=1){ 36 ch[0]->mul(a); 37 ch[1]->mul(a); 38 a=1u; 39 } 40 if(b){ 41 ch[0]->add(b); 42 ch[1]->add(b); 43 b=0u; 44 } 45 } 46 void refresh(){ 47 size=ch[0]->size+ch[1]->size+1; 48 sm=ch[0]->sm+ch[1]->sm;sm%=M;sm+=data;sm%=M; 49 } 50 }nodes[maxn],*null=nodes; 51 void dfs(int); 52 void add(node*,node*,uint); 53 void mul(node*,node*,uint); 54 uint qsum(node*,node*); 55 node *access(node*); 56 void makeroot(node*); 57 void link(node*,node*); 58 void cut(node*,node*); 59 void splay(node*); 60 void rot(node*,int); 61 vector<int>G[maxn]; 62 int n,m,prt[maxn]={0},x,y; 63 uint d; 64 char c; 65 int main(){ 66 freopen("nt2012_wym_tree.in","r",stdin); 67 freopen("nt2012_wym_tree.out","w",stdout); 68 null->ch[0]=null->ch[1]=null->p=null; 69 null->size=0; 70 scanf("%d%d",&n,&m); 71 for(int i=1;i<n;i++){ 72 scanf("%d%d",&x,&y); 73 G[x].push_back(y); 74 G[y].push_back(x); 75 } 76 dfs(1); 77 for(int i=1;i<=n;i++){ 78 nodes[i]=node(1); 79 nodes[i].ch[0]=nodes[i].ch[1]=null; 80 nodes[i].p=nodes+prt[i]; 81 } 82 while(m--){ 83 scanf(" %c%d%d",&c,&x,&y); 84 if(c=='+'){ 85 scanf("%u",&d); 86 add(nodes+x,nodes+y,d); 87 } 88 else if(c=='-'){ 89 cut(nodes+x,nodes+y); 90 scanf("%d%d",&x,&y); 91 link(nodes+x,nodes+y); 92 } 93 else if(c=='*'){ 94 scanf("%u",&d); 95 mul(nodes+x,nodes+y,d); 96 } 97 else if(c=='/')printf("%u ",qsum(nodes+x,nodes+y)); 98 } 99 return 0; 100 } 101 void dfs(int x){ 102 for(int i=0;i<(int)G[x].size();i++)if(G[x][i]!=prt[x]){ 103 prt[G[x][i]]=x; 104 dfs(G[x][i]); 105 } 106 } 107 void add(node *x,node *y,uint d){ 108 makeroot(x); 109 access(y)->add(d); 110 } 111 void mul(node *x,node *y,uint d){ 112 makeroot(x); 113 access(y)->mul(d); 114 } 115 uint qsum(node *x,node *y){ 116 makeroot(x); 117 return access(y)->sm; 118 } 119 node *access(node *x){ 120 node *y=null; 121 while(x!=null){ 122 splay(x); 123 x->ch[1]=y; 124 (y=x)->refresh(); 125 x=x->p; 126 } 127 return y; 128 } 129 void makeroot(node *x){ 130 access(x); 131 splay(x); 132 x->rev^=true; 133 } 134 void link(node *x,node *y){ 135 makeroot(x); 136 x->p=y; 137 } 138 void cut(node *x,node *y){ 139 makeroot(x); 140 access(y); 141 splay(y); 142 x->p=null; 143 y->ch[0]=null; 144 y->refresh(); 145 } 146 void splay(node *x){ 147 x->pushdown(); 148 while(!isroot(x)){ 149 if(!isroot(x->p))x->p->p->pushdown(); 150 x->p->pushdown(); 151 x->pushdown(); 152 if(isroot(x->p)){ 153 rot(x->p,dir(x)^1); 154 break; 155 } 156 if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1); 157 else rot(x->p,dir(x)^1); 158 rot(x->p,dir(x)^1); 159 } 160 } 161 void rot(node *x,int d){ 162 node *y=x->ch[d^1]; 163 x->ch[d^1]=y->ch[d]; 164 if(y->ch[d]!=null)y->ch[d]->p=x; 165 y->p=x->p; 166 if(!isroot(x))x->p->ch[dir(x)]=y; 167 y->ch[d]=x; 168 x->p=y; 169 x->refresh(); 170 y->refresh(); 171 }
也是LCT维护森林连通性的模板题。
话说一开始读错题了,以为是一般图,就写了一发分治并查集,然后发现LCT又好写又跑得快……
分治并查集的代码长度亮了……
分治并查集:
/************************************************************** Problem: 2049 User: hzoier Language: C++ Result: Accepted Time:4988 ms Memory:58572 kb ****************************************************************/ #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<map> using namespace std; const int maxn=10010,maxm=200010; inline int randint(){ static int a=1213,b=78181,c=49189487,x=987654321,p=998244353; x=a*x*x+b*x+c;x%=p;x+=p; return x%=p; } void addedge(int,int,int); void addquery(int,int,int); void solve(int,int,int); int findroot(int); void mergeset(int,int,vector<int>&); int prt[maxn]; map<pair<int,int>,int>mp; vector<int>u[maxm<<2],v[maxm<<2],stk[maxm<<2]; int qu[maxm<<2]={0},qv[maxm<<2]; int n,m,x,y,s,t; char c[15]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)prt[i]=i; for(int i=1;i<=m;i++){ scanf("%s%d%d",c,&x,&y); if(x>y)swap(x,y); if(*c=='C'){ if(!mp.count(make_pair(x,y)))mp[make_pair(x,y)]=i; } else if(*c=='D'){ s=mp[make_pair(x,y)]; t=i; addedge(1,m,1); mp.erase(make_pair(x,y)); } else{ t=i; addquery(1,m,1); } } t=m; for(map<pair<int,int>,int>::iterator it=mp.begin();it!=mp.end();it++){ x=it->first.first; y=it->first.second; s=it->second; addedge(1,m,1); } solve(1,m,1); return 0; } void addedge(int l,int r,int rt){ if(s<=l&&t>=r){ u[rt].push_back(x); v[rt].push_back(y); return; } int mid=(l+r)>>1; if(s<=mid)addedge(l,mid,rt<<1); if(t>mid)addedge(mid+1,r,rt<<1|1); } void addquery(int l,int r,int rt){ qu[rt]|=x; if(l==r){ qv[rt]=y; return; } int mid=(l+r)>>1; if(t<=mid)addquery(l,mid,rt<<1); else addquery(mid+1,r,rt<<1|1); } void solve(int l,int r,int rt){ if(!qu[rt])return; for(int i=0;i<(int)u[rt].size();i++)mergeset(u[rt][i],v[rt][i],stk[rt]); if(l==r)printf(findroot(qu[rt])==findroot(qv[rt])?"Yes ":"No "); else{ int mid=(l+r)>>1; solve(l,mid,rt<<1); solve(mid+1,r,rt<<1|1); } if(!stk[rt].empty())for(int i=(int)stk[rt].size()-1;i>=0;i--)prt[stk[rt][i]]=stk[rt][i]; } void mergeset(int x,int y,vector<int>&a){ x=findroot(x);y=findroot(y); if(x==y)return; if(randint()&1)swap(x,y); prt[x]=y; a.push_back(x); } int findroot(int x){ while(prt[x]!=x)x=prt[x]; return x; }
LCT:
1 /************************************************************** 2 Problem: 2049 3 User: hzoier 4 Language: C++ 5 Result: Accepted 6 Time:1656 ms 7 Memory:976 kb 8 ****************************************************************/ 9 10 #include<cstdio> 11 #include<cstring> 12 #include<algorithm> 13 #define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x))) 14 #define dir(x) ((int)((x)==(x)->p->ch[1])) 15 using namespace std; 16 const int maxn=10010; 17 struct node{ 18 bool rev; 19 node *ch[2],*p; 20 node():rev(false){} 21 void pushdown(){ 22 if(!rev)return; 23 ch[0]->rev^=true; 24 ch[1]->rev^=true; 25 swap(ch[0],ch[1]); 26 rev=false; 27 } 28 }nodes[maxn],*null=nodes; 29 node *access(node*); 30 void makeroot(node*); 31 void link(node*,node*); 32 void cut(node*,node*); 33 node *findroot(node*); 34 void splay(node*); 35 void rot(node*,int); 36 int n,m,x,y; 37 char c[15]; 38 int main(){ 39 null->ch[0]=null->ch[1]=null->p=null; 40 scanf("%d%d",&n,&m); 41 for(int i=1;i<=n;i++)nodes[i].ch[0]=nodes[i].ch[1]=nodes[i].p=null; 42 while(m--){ 43 scanf("%s%d%d",c,&x,&y); 44 if(*c=='C')link(nodes+x,nodes+y); 45 else if(*c=='D')cut(nodes+x,nodes+y); 46 else printf(findroot(nodes+x)==findroot(nodes+y)?"Yes ":"No "); 47 } 48 return 0; 49 } 50 node *access(node *x){ 51 node *y=null; 52 while(x!=null){ 53 splay(x); 54 x->ch[1]=y; 55 y=x; 56 x=x->p; 57 } 58 return y; 59 } 60 void makeroot(node *x){ 61 access(x); 62 splay(x); 63 x->rev^=true; 64 } 65 void link(node *x,node *y){ 66 makeroot(x); 67 x->p=y; 68 } 69 void cut(node *x,node *y){ 70 makeroot(x); 71 access(y); 72 splay(y); 73 y->ch[0]=null; 74 x->p=null; 75 } 76 node *findroot(node *x){ 77 access(x); 78 splay(x); 79 while(x->pushdown(),x->ch[0]!=null)x=x->ch[0]; 80 return x; 81 } 82 void splay(node *x){ 83 x->pushdown(); 84 while(!isroot(x)){ 85 if(!isroot(x->p))x->p->p->pushdown(); 86 x->p->pushdown(); 87 x->pushdown(); 88 if(isroot(x->p)){ 89 rot(x->p,dir(x)^1); 90 break; 91 } 92 if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1); 93 else rot(x->p,dir(x)^1); 94 rot(x->p,dir(x)^1); 95 } 96 } 97 void rot(node *x,int d){ 98 node *y=x->ch[d^1]; 99 x->ch[d^1]=y->ch[d]; 100 if(y->ch[d]!=null)y->ch[d]->p=x; 101 y->p=x->p; 102 if(!isroot(x))x->p->ch[dir(x)]=y; 103 y->ch[d]=x; 104 x->p=y; 105 }
只有加边的动态MST,LCT维护即可。
注意加虚点来维护边权。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<map> 5 #define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x))) 6 #define dir(x) ((int)((x)==(x)->p->ch[1])) 7 using namespace std; 8 const int maxn=510; 9 struct node{ 10 int data,mx,pos; 11 node *ch[2],*p; 12 bool rev; 13 node(int d):data(d),mx(d),pos(-1),rev(false){} 14 void pushdown(){ 15 if(!rev)return; 16 if(pos!=-1)pos^=1; 17 ch[0]->rev^=true; 18 ch[1]->rev^=true; 19 swap(ch[0],ch[1]); 20 rev=false; 21 } 22 void refresh(){ 23 mx=data; 24 pos=-1; 25 if(ch[0]->mx>mx){ 26 mx=ch[0]->mx; 27 pos=0; 28 } 29 if(ch[1]->mx>mx){ 30 mx=ch[1]->mx; 31 pos=1; 32 } 33 } 34 }*null=new node(-1000000); 35 node *newnode(int); 36 node *access(node*); 37 void makeroot(node*); 38 void cut(node*,node*); 39 void link(node*,node*); 40 node *getroot(node*); 41 node *getmax(node*,node*); 42 void splay(node*); 43 void rot(node*,int); 44 map<node*,pair<node*,node*> >mp; 45 node *iter[maxn]; 46 int n,m,cnt=0,x,y,w,ans=0; 47 node *tmp; 48 int main(){ 49 freopen("road.in","r",stdin); 50 freopen("road.out","w",stdout); 51 null->ch[0]=null->ch[1]=null->p=null; 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;i++)iter[i]=newnode(-1000000); 54 while(m--){ 55 scanf("%d%d%d",&x,&y,&w); 56 if(getroot(iter[x])!=getroot(iter[y])){ 57 tmp=newnode(w); 58 mp[tmp]=make_pair(iter[x],iter[y]); 59 link(tmp,iter[x]); 60 link(tmp,iter[y]); 61 ans+=w; 62 cnt++; 63 } 64 else{ 65 node *tmp=getmax(iter[x],iter[y]); 66 if(tmp->data>w){ 67 ans-=tmp->data; 68 cut(tmp,mp[tmp].first); 69 cut(tmp,mp[tmp].second); 70 tmp->data=w; 71 mp[tmp]=make_pair(iter[x],iter[y]); 72 link(tmp,iter[x]); 73 link(tmp,iter[y]); 74 ans+=w; 75 } 76 } 77 if(cnt==n-1)printf("%.1lf ",(double)ans/2.0); 78 else printf("0 "); 79 } 80 return 0; 81 } 82 node *newnode(int d){ 83 node *x=new node(d); 84 x->ch[0]=x->ch[1]=x->p=null; 85 return x; 86 } 87 node *access(node *x){ 88 node *y=null; 89 while(x!=null){ 90 splay(x); 91 x->ch[1]=y; 92 (y=x)->refresh(); 93 x=x->p; 94 } 95 return y; 96 } 97 void makeroot(node *x){ 98 access(x); 99 splay(x); 100 x->rev^=true; 101 } 102 void cut(node *x,node *y){ 103 makeroot(x); 104 access(y); 105 splay(y); 106 x->p=null; 107 y->ch[0]=null; 108 y->refresh(); 109 } 110 void link(node *x,node *y){ 111 makeroot(x); 112 x->p=y; 113 } 114 node *getroot(node *x){ 115 x=access(x); 116 while(x->pushdown(),x->ch[0]!=null)x=x->ch[0]; 117 splay(x); 118 return x; 119 } 120 node *getmax(node *x,node *y){ 121 makeroot(x); 122 x=access(y); 123 while(x->pushdown(),x->pos!=-1)x=x->ch[x->pos]; 124 return x; 125 } 126 void splay(node *x){ 127 x->pushdown(); 128 while(!isroot(x)){ 129 if(!isroot(x->p))x->p->p->pushdown(); 130 x->p->pushdown(); 131 x->pushdown(); 132 if(isroot(x->p)){ 133 rot(x->p,dir(x)^1); 134 break; 135 } 136 if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1); 137 else rot(x->p,dir(x)^1); 138 rot(x->p,dir(x)^1); 139 } 140 } 141 void rot(node *x,int d){ 142 node *y=x->ch[d^1]; 143 x->ch[d^1]=y->ch[d]; 144 if(y->ch[d]!=null)y->ch[d]->p=x; 145 y->p=x->p; 146 if(!isroot(x))x->p->ch[dir(x)]=y; 147 y->ch[d]=x; 148 x->p=y; 149 x->refresh(); 150 y->refresh(); 151 }
只有删边的动态MST,时光倒流之后就转成了只有加边的动态MST,仍然LCT维护。
话说初始MST一开始我是直接用LCT构建的,后来一看怎么我跑得这么慢才发现大家都是用的Kruskal……然后写了一发Prim,发现仍然很慢……= =
直接LCT:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<map> 5 #define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x))) 6 #define dir(x) ((int)((x)==(x)->p->ch[1])) 7 using namespace std; 8 const int maxn=1000010; 9 template<class T>inline void readint(T &x){ 10 static int c=0; 11 x=0; 12 while(c!=EOF&&(c<'0'||c>'9'))c=getchar(); 13 if(c==EOF)return; 14 while(c>='0'&&c<='9'){ 15 x=(x<<1)+(x<<3)+(c^48); 16 c=getchar(); 17 } 18 } 19 struct node{ 20 int data,mx,pos; 21 node *ch[2],*p; 22 bool rev; 23 node(int d=-1000000):data(d),mx(d),pos(-1),rev(false){} 24 void pushdown(){ 25 if(!rev)return; 26 if(pos!=-1)pos^=1; 27 ch[0]->rev^=true; 28 ch[1]->rev^=true; 29 swap(ch[0],ch[1]); 30 rev=false; 31 } 32 void refresh(){ 33 mx=data; 34 pos=-1; 35 if(ch[0]->mx>mx){ 36 mx=ch[0]->mx; 37 pos=0; 38 } 39 if(ch[1]->mx>mx){ 40 mx=ch[1]->mx; 41 pos=1; 42 } 43 } 44 }nodes[maxn<<1],*null=nodes,*ptr; 45 struct A{int tp,x,y,w;}a[maxn<<1]; 46 node *newnode(int); 47 node *access(node*); 48 void makeroot(node*); 49 void link(node*,node*); 50 void cut(node*,node*); 51 node *getroot(node*); 52 node *getmax(node*,node*); 53 void splay(node*); 54 void rot(node*,int); 55 int n,m,q,ans[maxn<<1]; 56 map<node*,pair<node*,node*> >mp; 57 map<pair<int,int>,int>e; 58 int main(){ 59 freopen("tube_strong.in","r",stdin); 60 freopen("tube_strong.out","w",stdout); 61 null->ch[0]=null->ch[1]=null->p=null; 62 readint(n); 63 readint(m); 64 readint(q); 65 ptr=nodes+n; 66 for(int i=1;i<=n;i++)nodes[i].ch[0]=nodes[i].ch[1]=nodes[i].p=null; 67 while(m--){ 68 int x,y,w; 69 readint(x); 70 readint(y); 71 readint(w); 72 if(x>y)swap(x,y); 73 e[make_pair(x,y)]=w; 74 } 75 m=q; 76 for(int i=1;i<=m;i++){ 77 readint(a[i].tp); 78 readint(a[i].x); 79 readint(a[i].y); 80 if(a[i].x>a[i].y)swap(a[i].x,a[i].y); 81 if(a[i].tp==2){ 82 a[i].w=e[make_pair(a[i].x,a[i].y)]; 83 e.erase(make_pair(a[i].x,a[i].y)); 84 } 85 } 86 for(map<pair<int,int>,int>::iterator it=e.begin();it!=e.end();it++){ 87 a[++m].tp=2; 88 a[m].x=it->first.first; 89 a[m].y=it->first.second; 90 a[m].w=it->second; 91 } 92 for(int i=m;i;i--){ 93 int x=a[i].x,y=a[i].y,w=a[i].w; 94 if(a[i].tp==1)ans[i]=getmax(nodes+x,nodes+y)->data; 95 else{ 96 node *tmp; 97 if(getroot(nodes+x)!=getroot(nodes+y)){ 98 tmp=newnode(w); 99 link(tmp,nodes+x); 100 link(tmp,nodes+y); 101 mp[tmp]=make_pair(nodes+x,nodes+y); 102 } 103 else{ 104 tmp=getmax(nodes+x,nodes+y); 105 if(tmp->data>w){ 106 cut(tmp,mp[tmp].first); 107 cut(tmp,mp[tmp].second); 108 tmp->data=w; 109 link(tmp,nodes+x); 110 link(tmp,nodes+y); 111 mp[tmp]=make_pair(nodes+x,nodes+y); 112 } 113 } 114 } 115 } 116 for(int i=1;i<=m;i++)if(a[i].tp==1)printf("%d ",ans[i]); 117 return 0; 118 } 119 node *newnode(int d){ 120 *++ptr=node(d); 121 ptr->ch[0]=ptr->ch[1]=ptr->p=null; 122 return ptr; 123 } 124 node *access(node *x){ 125 node *y=null; 126 while(x!=null){ 127 splay(x); 128 x->ch[1]=y; 129 (y=x)->refresh(); 130 x=x->p; 131 } 132 return y; 133 } 134 void makeroot(node *x){ 135 access(x); 136 splay(x); 137 x->rev^=true; 138 } 139 void link(node *x,node *y){ 140 makeroot(x); 141 x->p=y; 142 } 143 void cut(node *x,node *y){ 144 makeroot(x); 145 access(y); 146 splay(y); 147 y->ch[0]=null; 148 x->p=null; 149 y->refresh(); 150 } 151 node *getroot(node *x){ 152 x=access(x); 153 while(x->pushdown(),x->ch[0]!=null)x=x->ch[0]; 154 splay(x); 155 return x; 156 } 157 node *getmax(node *x,node *y){ 158 makeroot(x); 159 x=access(y); 160 while(x->pushdown(),x->pos!=-1)x=x->ch[x->pos]; 161 splay(x); 162 return x; 163 } 164 void splay(node *x){ 165 x->pushdown(); 166 while(!isroot(x)){ 167 if(!isroot(x->p))x->p->p->pushdown(); 168 x->p->pushdown(); 169 x->pushdown(); 170 if(isroot(x->p)){ 171 rot(x->p,dir(x)^1); 172 break; 173 } 174 if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1); 175 else rot(x->p,dir(x)^1); 176 rot(x->p,dir(x)^1); 177 } 178 } 179 void rot(node *x,int d){ 180 node *y=x->ch[d^1]; 181 x->ch[d^1]=y->ch[d]; 182 if(y->ch[d]!=null)y->ch[d]->p=x; 183 y->p=x->p; 184 if(!isroot(x))x->p->ch[dir(x)]=y; 185 y->ch[d]=x; 186 x->p=y; 187 x->refresh(); 188 y->refresh(); 189 }
Prim:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<map> 5 #include<vector> 6 #include<queue> 7 #define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x))) 8 #define dir(x) ((int)((x)==(x)->p->ch[1])) 9 using namespace std; 10 const int maxn=1000010; 11 template<class T>inline void readint(T &x){ 12 static int c=0; 13 x=0; 14 while(c!=EOF&&(c<'0'||c>'9'))c=getchar(); 15 if(c==EOF)return; 16 while(c>='0'&&c<='9'){ 17 x=(x<<1)+(x<<3)+(c^48); 18 c=getchar(); 19 } 20 } 21 struct node{ 22 int data,mx,pos; 23 node *ch[2],*p; 24 bool rev; 25 node(int d=-1000000):data(d),mx(d),pos(-1),rev(false){} 26 void pushdown(){ 27 if(!rev)return; 28 if(pos!=-1)pos^=1; 29 ch[0]->rev^=true; 30 ch[1]->rev^=true; 31 swap(ch[0],ch[1]); 32 rev=false; 33 } 34 void refresh(){ 35 mx=data; 36 pos=-1; 37 if(ch[0]->mx>mx){ 38 mx=ch[0]->mx; 39 pos=0; 40 } 41 if(ch[1]->mx>mx){ 42 mx=ch[1]->mx; 43 pos=1; 44 } 45 } 46 }nodes[maxn<<1],*null=nodes,*ptr; 47 struct oper{int tp,x,y,w;}a[maxn]; 48 struct A{ 49 int x,dis; 50 A(int x,int dis):x(x),dis(dis){} 51 bool operator<(const A &a)const{return dis>a.dis;} 52 }; 53 void Prim(); 54 node *newnode(int); 55 node *access(node*); 56 void makeroot(node*); 57 void link(node*,node*); 58 void cut(node*,node*); 59 node *getmax(node*,node*); 60 void splay(node*); 61 void rot(node*,int); 62 vector<int>G[maxn],W[maxn]; 63 int dis[maxn],prt[maxn]={0}; 64 bool vis[maxn]={false}; 65 int n,m,q,ans[maxn]; 66 map<node*,pair<node*,node*> >mp; 67 map<pair<int,int>,int>e; 68 int main(){ 69 freopen("tube_strong.in","r",stdin); 70 freopen("tube_strong.out","w",stdout); 71 null->ch[0]=null->ch[1]=null->p=null; 72 readint(n); 73 readint(m); 74 readint(q); 75 ptr=nodes+n; 76 for(int i=1;i<=n;i++)nodes[i].ch[0]=nodes[i].ch[1]=nodes[i].p=null; 77 while(m--){ 78 int x,y,w; 79 readint(x); 80 readint(y); 81 readint(w); 82 if(x>y)swap(x,y); 83 e[make_pair(x,y)]=w; 84 } 85 m=q; 86 for(int i=1;i<=m;i++){ 87 readint(a[i].tp); 88 readint(a[i].x); 89 readint(a[i].y); 90 if(a[i].x>a[i].y)swap(a[i].x,a[i].y); 91 if(a[i].tp==2){ 92 a[i].w=e[make_pair(a[i].x,a[i].y)]; 93 e.erase(make_pair(a[i].x,a[i].y)); 94 } 95 } 96 for(map<pair<int,int>,int>::iterator it=e.begin();it!=e.end();it++){ 97 G[it->first.first].push_back(it->first.second); 98 W[it->first.first].push_back(it->second); 99 G[it->first.second].push_back(it->first.first); 100 W[it->first.second].push_back(it->second); 101 } 102 Prim(); 103 for(int i=m;i;i--){ 104 int x=a[i].x,y=a[i].y,w=a[i].w; 105 if(a[i].tp==1)ans[i]=getmax(nodes+x,nodes+y)->data; 106 else{ 107 node *tmp=getmax(nodes+x,nodes+y); 108 if(tmp->data>w){ 109 cut(tmp,mp[tmp].first); 110 cut(tmp,mp[tmp].second); 111 tmp->data=w; 112 link(tmp,nodes+x); 113 link(tmp,nodes+y); 114 mp[tmp]=make_pair(nodes+x,nodes+y); 115 } 116 } 117 } 118 for(int i=1;i<=m;i++)if(a[i].tp==1)printf("%d ",ans[i]); 119 return 0; 120 } 121 void Prim(){ 122 fill(dis+1,dis+n+1,0x3f3f3f3f); 123 priority_queue<A>q; 124 dis[1]=0; 125 q.push(A(1,0)); 126 while(!q.empty()){ 127 int x=q.top().x; 128 q.pop(); 129 if(vis[x])continue; 130 vis[x]=true; 131 for(int i=0;i<(int)G[x].size();i++)if(!vis[G[x][i]]&&dis[G[x][i]]>W[x][i]){ 132 dis[G[x][i]]=W[x][i]; 133 prt[G[x][i]]=x; 134 q.push(A(G[x][i],W[x][i])); 135 } 136 } 137 for(int i=2;i<=n;i++){ 138 node *x=newnode(dis[i]); 139 x->p=nodes+prt[i]; 140 nodes[i].p=x; 141 mp[x]=make_pair(nodes+min(prt[i],i),nodes+max(prt[i],i)); 142 } 143 } 144 node *newnode(int d){ 145 *++ptr=node(d); 146 ptr->ch[0]=ptr->ch[1]=ptr->p=null; 147 return ptr; 148 } 149 node *access(node *x){ 150 node *y=null; 151 while(x!=null){ 152 splay(x); 153 x->ch[1]=y; 154 (y=x)->refresh(); 155 x=x->p; 156 } 157 return y; 158 } 159 void makeroot(node *x){ 160 access(x); 161 splay(x); 162 x->rev^=true; 163 } 164 void link(node *x,node *y){ 165 makeroot(x); 166 x->p=y; 167 } 168 void cut(node *x,node *y){ 169 makeroot(x); 170 access(y); 171 splay(y); 172 y->ch[0]=null; 173 x->p=null; 174 y->refresh(); 175 } 176 node *getmax(node *x,node *y){ 177 makeroot(x); 178 x=access(y); 179 while(x->pushdown(),x->pos!=-1)x=x->ch[x->pos]; 180 splay(x); 181 return x; 182 } 183 void splay(node *x){ 184 x->pushdown(); 185 while(!isroot(x)){ 186 if(!isroot(x->p))x->p->p->pushdown(); 187 x->p->pushdown(); 188 x->pushdown(); 189 if(isroot(x->p)){ 190 rot(x->p,dir(x)^1); 191 break; 192 } 193 if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1); 194 else rot(x->p,dir(x)^1); 195 rot(x->p,dir(x)^1); 196 } 197 } 198 void rot(node *x,int d){ 199 node *y=x->ch[d^1]; 200 x->ch[d^1]=y->ch[d]; 201 if(y->ch[d]!=null)y->ch[d]->p=x; 202 y->p=x->p; 203 if(!isroot(x))x->p->ch[dir(x)]=y; 204 y->ch[d]=x; 205 x->p=y; 206 x->refresh(); 207 y->refresh(); 208 }
话说这两份代码bzoj上都T到死,也是没谁了……
这才是真·动态MST……
听说有个算法叫CDQ重构图,然而太神了并不能看懂,于是乎写了一发对时间分治+LCT,常数大如dog,成功被卡掉……
反正各种卡常都过不去,我还是贴没卡常的代码好了……
1 /************************************************************** 2 Problem: 2001 3 User: hzoier 4 Language: C++ 5 Result: Time_Limit_Exceed 6 ****************************************************************/ 7 8 #include<cstdio> 9 #include<cstring> 10 #include<algorithm> 11 #include<vector> 12 #include<map> 13 #define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x))) 14 #define dir(x) ((int)((x)==(x)->p->ch[1])) 15 using namespace std; 16 const int maxn=20010,maxm=50010; 17 struct node{ 18 int data,mx,pos; 19 node *ch[2],*p; 20 bool rev; 21 node(int d=-1000000):data(d),mx(d),pos(-1),rev(false){} 22 void pushdown(){ 23 if(!rev)return; 24 if(pos!=-1)pos^=1; 25 ch[0]->rev^=1; 26 ch[1]->rev^=1; 27 swap(ch[0],ch[1]); 28 rev=false; 29 } 30 void refresh(){ 31 mx=data; 32 pos=-1; 33 if(ch[0]->mx>mx){ 34 mx=ch[0]->mx; 35 pos=0; 36 } 37 if(ch[1]->mx>mx){ 38 mx=ch[1]->mx; 39 pos=1; 40 } 41 } 42 }nodes[maxn<<1],*null=nodes,*ptr=nodes; 43 struct edge{int x,y,t,w;}e[maxm]; 44 struct A{ 45 node *x,*u,*v; 46 int w; 47 A(node *x,node *u,node *v,int w):x(x),u(u),v(v),w(w){} 48 }; 49 void addedge(int,int,int); 50 void solve(int,int,int,long long); 51 node *newnode(int); 52 node *access(node*); 53 void makeroot(node*); 54 void link(node*,node*); 55 void cut(node*,node*); 56 node *getmax(node*,node*); 57 node *getroot(node*); 58 void splay(node*); 59 void rot(node*,int); 60 vector<int>u[maxm<<2],v[maxm<<2],w[maxm<<2]; 61 map<node*,pair<node*,node*> >mp; 62 int n,m,q,s,t,k,x,y,z; 63 node *tmp; 64 int main(){ 65 null->ch[0]=null->ch[1]=null->p=null; 66 scanf("%d%d%d",&n,&m,&q); 67 for(int i=1;i<=n;i++)newnode(-100000000); 68 for(int i=1;i<n;i++){ 69 tmp=newnode(100000000); 70 link(tmp,nodes+i); 71 link(tmp,nodes+i+1); 72 mp[tmp]=make_pair(nodes+i,nodes+i+1); 73 } 74 for(int i=1;i<=m;i++){ 75 scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w); 76 if(e[i].x>e[i].y)swap(e[i].x,e[i].y); 77 e[i].t=1; 78 } 79 for(int i=1;i<=q;i++){ 80 scanf("%d%d",&k,&z); 81 x=e[k].x;y=e[k].y; 82 s=e[k].t;t=i-1; 83 swap(e[k].w,z); 84 if(t)addedge(1,q,1); 85 e[k].t=i; 86 } 87 for(int i=1;i<=m;i++){ 88 s=e[i].t;t=q; 89 x=e[i].x;y=e[i].y;z=e[i].w; 90 addedge(1,q,1); 91 } 92 solve(1,q,1,(long long)(n-1)*100000000); 93 return 0; 94 } 95 void addedge(int l,int r,int rt){ 96 if(s<=l&&t>=r){ 97 u[rt].push_back(x); 98 v[rt].push_back(y); 99 w[rt].push_back(z); 100 return; 101 } 102 int mid=(l+r)>>1; 103 if(s<=mid)addedge(l,mid,rt<<1); 104 if(t>mid)addedge(mid+1,r,rt<<1|1); 105 } 106 void solve(int l,int r,int rt,long long ans){ 107 vector<A>stk; 108 for(int i=0;i<(int)u[rt].size();i++){ 109 tmp=getmax(nodes+u[rt][i],nodes+v[rt][i]); 110 if(tmp->data>w[rt][i]){ 111 stk.push_back(A(tmp,mp[tmp].first,mp[tmp].second,tmp->data)); 112 cut(tmp,mp[tmp].first); 113 cut(tmp,mp[tmp].second); 114 ans-=tmp->data; 115 mp[tmp]=make_pair(nodes+u[rt][i],nodes+v[rt][i]); 116 tmp->data=w[rt][i]; 117 link(tmp,nodes+u[rt][i]); 118 link(tmp,nodes+v[rt][i]); 119 ans+=w[rt][i]; 120 } 121 } 122 if(l==r)printf("%lld ",ans); 123 else{ 124 int mid=(l+r)>>1; 125 solve(l,mid,rt<<1,ans); 126 solve(mid+1,r,rt<<1|1,ans); 127 } 128 if(!stk.empty())for(int i=(int)stk.size()-1;i>=0;i--){ 129 cut(stk[i].x,mp[stk[i].x].first); 130 cut(stk[i].x,mp[stk[i].x].second); 131 mp[stk[i].x]=make_pair(stk[i].u,stk[i].v); 132 stk[i].x->data=stk[i].w; 133 link(stk[i].x,stk[i].u); 134 link(stk[i].x,stk[i].v); 135 } 136 } 137 node *newnode(int d){ 138 *++ptr=node(d); 139 ptr->ch[0]=ptr->ch[1]=ptr->p=null; 140 return ptr; 141 } 142 node *access(node *x){ 143 node *y=null; 144 while(x!=null){ 145 splay(x); 146 x->ch[1]=y; 147 (y=x)->refresh(); 148 x=x->p; 149 } 150 return y; 151 } 152 void makeroot(node *x){ 153 access(x); 154 splay(x); 155 x->rev^=true; 156 } 157 void link(node *x,node *y){ 158 makeroot(x); 159 x->p=y; 160 } 161 void cut(node *x,node *y){ 162 makeroot(x); 163 access(y); 164 splay(y); 165 y->ch[0]=null; 166 x->p=null; 167 y->refresh(); 168 } 169 node *getmax(node *x,node *y){ 170 makeroot(x); 171 x=access(y); 172 while(x->pushdown(),x->pos!=-1)x=x->ch[x->pos]; 173 splay(x); 174 return x; 175 } 176 node *getroot(node *x){ 177 x=access(x); 178 while(x->pushdown(),x->ch[0]!=null)x=x->ch[0]; 179 splay(x); 180 return x; 181 } 182 void splay(node *x){ 183 x->pushdown(); 184 while(!isroot(x)){ 185 if(!isroot(x->p))x->p->p->pushdown(); 186 x->p->pushdown(); 187 x->pushdown(); 188 if(isroot(x->p)){ 189 rot(x->p,dir(x)^1); 190 break; 191 } 192 if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1); 193 else rot(x->p,dir(x)^1); 194 rot(x->p,dir(x)^1); 195 } 196 } 197 void rot(node *x,int d){ 198 node *y=x->ch[d^1]; 199 x->ch[d^1]=y->ch[d]; 200 if(y->ch[d]!=null)y->ch[d]->p=x; 201 y->p=x->p; 202 if(!isroot(x))x->p->ch[dir(x)]=y; 203 y->ch[d]=x; 204 x->p=y; 205 x->refresh(); 206 y->refresh(); 207 }
话说写这题的时候调了半天,最后发现我pushdown的时候忘了交换左右儿子,真是智障……
感觉这几道题还好吧……每道题都是重新打的LCT(虽然调不出来的时候会拿出上一题的代码手动FC……),感觉考试考到的话模板应该是打不错了。
LCT真是累啊……算了我接下来还是专心搞网络流好了……