bzoj3159: 决战 树链剖分+splay
Posted f321dd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3159: 决战 树链剖分+splay相关的知识,希望对你有一定的参考价值。
方法很简单,树剖,把区间提取出来,打翻转标记,再放回去。
注意:由于某种原因,我写的是把题目中的r忽略掉的一般情况,否则简单得多。
于是本以为写起来也很简单ovo
结果发现非常繁琐,最后写得又长跑得又慢。
#include<bits/stdc++.h> #define L(t) (t)->c[0] #define R(t) (t)->c[1] #define Z(t) (L(t)->s+1) #define N 50005 #define M (s+t>>1) #define u first #define v second #define int long long using namespace std; struct edge{ edge* s; int v; }e[N*2],*back(e),*h[N]; void add(int u,int v){ h[u]=&(*back++ =(edge){h[u],v}); h[v]=&(*back++ =(edge){h[v],u}); } typedef int ds[N]; ds d,p,num,size,son,top; void dfs1(int u){ d[u]=d[p[u]]+1; size[u]=1; int s=0; for(edge* i=h[u];i;i=i->s) if(i->v!=p[u]){ p[i->v]=u; dfs1(i->v); size[u]+=size[i->v]; if(s<size[i->v]) s=size[son[u]=i->v]; } } void dfs2(int u){ static int tot; num[u]=++tot; if(size[u]!=1){ top[son[u]]=top[u]; dfs2(son[u]); } for(edge* i=h[u];i;i=i->s) if(i->v!=p[u] &&i->v!=son[u]) dfs2(top[i->v]=i->v); } struct node{ int a[3],s,u,v; bool rev; node *c[2]; }tin[N],*next=tin, zinc={0,1e9}, *null=&zinc,*root; int Sum(int u,int v){ return u+v; } int Min(int u,int v){ return u<v?u:v; } int Max(int u,int v){ return u<v?v:u; } int(*f[3])(int,int) ={Sum,Min,Max}; int devolve(node* t){ if(t==null) return 0; if(t->rev){ L(t)->rev^=1; R(t)->rev^=1; t->rev=0; swap(L(t),R(t)); } if(int u=t->u){ t->u=0; L(t)->u+=u; R(t)->u+=u; t->a[1]+=u; t->a[2]+=u; t->v+=u; t->a[0]+=u*t->s; } return Z(t); } node* update(node* t){ devolve(L(t)); devolve(R(t)); for(int i=0;i!=3;++i) t->a[i]=f[i](f[i]( L(t)->a[i], R(t)->a[i]),t->v); t->s=R(t)->s+Z(t); return t; } void link(bool i, node*& t,node*& s){ node* d=t->c[i]; t->c[i]=s; s=update(t),t=d; } node* splay(int v, node*& t=root){ node* d[]={null,null}; while(v!=devolve(t)){ bool i=v>Z(t); v-=i*Z(t); if(v!=devolve(t->c[i]) &&i==v>Z(t->c[i])){ v-=i*Z(t->c[i]); link(i,t, t->c[i]->c[i^1]); } link(i,t,d[i]); } for(int i=0;i!=2;++i){ node* s=t->c[i^1]; while(d[i]!=null) link(i,d[i],s); t->c[i^1]=s; } return update(t); } node*& splay(int s,int t){ splay(s); return L(splay( t-s+2,R(root))); } node* build(int s,int t){ if(s<=t){ node* i=next++; L(i)=build(s,M-1); R(i)=build(M+1,t); return update(i); } return null; } typedef pair<int,int> vec; vec* u=new vec[N]; vec* v=new vec[N]; int solve(int i,int j, vec*& u,vec*& v){ vec **s=&u,**t=&v; for(;top[i]!=top[j]; i=p[top[i]]){ if(d[top[i]]<d[top[j]]) swap(i,j), swap(s,t); *(*s)++=vec( num[top[i]],num[i]); } if(d[i]<d[j]) swap(i,j), swap(s,t); *(*s)++=vec(num[j],num[i]); return num[j]; } void amend(int p,int q,int j){ vec *s=u,*t=v; solve(p,q,s,t); while(s--!=u) splay( s->u,s->v)->u+=j; while(t--!=v) splay( t->u,t->v)->u+=j; } int query(int p,int q,int i){ int j=i^1?0:1e9; vec *s=u,*t=v; solve(p,q,s,t); while(s--!=u) j=f[i](j,splay( s->u,s->v)->a[i]); while(t--!=v) j=f[i](j,splay( t->u,t->v)->a[i]); return j; } void invert(int p,int q){ int f=0; node **x,*j=null,*k=null; vec *y,*s=u,*t=v; int e=solve(p,q,s,t); if(u!=s&&v!=t&&u->u<v->v) swap(u,v), swap(s,t); for(vec* i=u;i!=s;++i) if(i->u==e||i->v==e) x=&j,y=i; else{ f+=i->v-i->u+1; node*& a=splay( i->u,i->v); R(splay(a->s,a))=j; update(j=a),a=null; } for(vec* i=v;i!=t;++i) if(i->u==e||i->v==e) x=&k,y=i; else{ node*& a=splay( i->u,i->v); R(splay(a->s,a))=k; update(k=a),a=null; } if(vec* i=y){ if(x==&j) f+=i->v-i->u+1; node*& a=splay( i->u,i->v); R(splay(a->s,a))=*x; update(*x=a),a=null; } if(!f)k->rev=1; else{ j->rev=1; R(splay(j->s,j))=k; update(j)->rev=1; k=R(splay(f,j)); R(j)=null; update(j)->rev=1; } if(vec* i=y){ node*& a=splay( i->u,i->u-1); *x=R(splay(i->v -i->u+1,a=*x)); R(a)=null,update(a); } for(vec* i=t-1;i>=v;--i) if(i!=y){ node*& a=splay( i->u,i->u-1); k=R(splay(i->v -i->u+1,a=k)); R(a)=null,update(a); } for(vec* i=s-1;i>=u;--i) if(i!=y){ node*& a=splay( i->u,i->u-1); j=R(splay(i->v -i->u+1,a=j)); R(a)=null,update(a); } } #undef int int main(){ int n,m,s,t,u; char a[10]; scanf("%d%d%*d",&n,&m); root=build(0,n+1); for(int i=1;i!=n;++i){ scanf("%d%d",&s,&t); add(s,t); } dfs1(1); dfs2(top[1]=1); while(m--){ scanf("%s%d%d",a,&s,&t); switch(a[2]){ case‘v‘: invert(s,t); break; case‘c‘: scanf("%d",&u); amend(s,t,u); break; default: printf("%lld\n", query(s,t,a[2] ==‘j‘?2:a[2]!=‘m‘)); } } }
以上是关于bzoj3159: 决战 树链剖分+splay的主要内容,如果未能解决你的问题,请参考以下文章