HDU 5467
第一次写LCT,各种模板加入。。。以后都只遇到有新意的题目再更新了
这道题就是LCT,但是,难在一个回退的操作。这时,可以通过改变执行顺序,先把要回退后再做的操作先执行了,再回退到之前的执行。这时,建立一棵操作树,使用DFS可以回退的特点,就能完成这一功能。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <set> #pragma comment(linker, "/STACK:1024000000,1024000000") #define LL long long using namespace std; const int MAX=300050; const LL MOD=1e9+7; int fa[MAX],ch[MAX][2],son[MAX],nxt[MAX],rev[MAX]; int n,q; int opt_x[MAX],opt_u[MAX],opt_v[MAX],opt_d[MAX]; LL val[MAX],mul[MAX]; LL ans[MAX]; set<long long>st; int stack[MAX]; void update(int x){ int l=ch[x][0],r=ch[x][1]; mul[x]=val[x]; if(l) mul[x]=mul[x]*mul[l]%MOD; if(r) mul[x]=mul[x]*mul[r]%MOD; } void pushdown(int x){ int l=ch[x][0],r=ch[x][1]; if(rev[x]){ rev[x]^=1;rev[l]^=1;rev[r]^=1; swap(ch[x][0],ch[x][1]); } } bool isroot(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; } void rotate(int x){ int y=fa[x],z=fa[y],l,r; if(ch[y][0]==x)l=0;else l=1;r=l^1; if(!isroot(y)) { if(ch[z][0]==y)ch[z][0]=x; else ch[z][1]=x; } fa[x]=z;fa[y]=x;fa[ch[x][r]]=y; ch[y][l]=ch[x][r];ch[x][r]=y; update(y);update(x); } void splay(int u){ int top=0; stack[++top]=u; for(int i=u;!isroot(i);i=fa[i]) stack[++top]=fa[i]; while(top) pushdown(stack[top--]); while(!isroot(u)){ int y=fa[u],z=fa[y]; if(!isroot(y)){ if(ch[y][0]==u^ch[z][0]==y)rotate(u); else rotate(y); } rotate(u); } } bool connect(int u,int v){ while(fa[u]) u=fa[u]; while(fa[v]) v=fa[v]; return u==v; } void access(int u){ for(int t=0;u;t=u,u=fa[u]){ splay(u),ch[u][1]=t,update(u); } } void makeroot(int x){ access(x),splay(x),rev[x]^=1; } bool link(int u,int v){ if(u>v) swap(u,v); if(u==v) return false; if(connect(u,v)) return false; makeroot(u),fa[u]=v; st.insert(MAX*u+v); return true; } bool cut(int u,int v){ if(u>v) swap(u,v); if(u==v) return false; if(st.find(MAX*u+v)==st.end()) return false; makeroot(u),access(v),splay(v); fa[u]=0,ch[v][0]=0; st.erase(MAX*u+v); return true; } void dfs(int x){ bool done=false; LL tmp; int u=opt_u[x],v=opt_v[x]; if(opt_x[x]==1) done=link(u,v); if(opt_x[x]==2) done=cut(u,v); if(opt_x[x]==4){ if(u==v) ans[opt_d[x]]=val[u]; else{ if(connect(u,v)){ makeroot(u); access(v),splay(v); ans[opt_d[x]]=mul[v]; } else{ ans[opt_d[x]]=0; } } } if(opt_x[x]==5){ done=true; splay(u); tmp=val[u]; val[u]=v*(v-1)/2%MOD; update(u); } for(int i=son[x];i;i=nxt[i]) dfs(i); if(done){ if(opt_x[x]==1) done=cut(u,v); if(opt_x[x]==2) done=link(u,v); if(opt_x[x]==5){ splay(u); val[u]=tmp; update(u); } } } int main(){ int T; LL k; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&q); for(int i=1;i<=n;i++){ scanf("%lld",&k); val[i]=mul[i]=k*(k-1)/2%MOD; } for(int i=0;i<=n+10;i++) rev[i]=0,fa[i]=0,ch[i][0]=ch[i][1]=0; for(int i=0;i<=q+10;i++) nxt[i]=son[i]=0; st.clear(); int tot=0; for(int i=1;i<=q;i++){ scanf("%d",&opt_x[i]); if(opt_x[i]==3){ scanf("%d",&opt_u[i]); nxt[i]=son[opt_u[i]],son[opt_u[i]]=i; } else{ scanf("%d%d",&opt_u[i],&opt_v[i]); nxt[i]=son[i-1],son[i-1]=i; if(opt_x[i]==4){ opt_d[i]=++tot; } } } dfs(0); for(int i=1;i<=tot;i++){ printf("%lld\n",ans[i]); } } return 0; }