LCT 填坑系列
清华冬令营 T1用了LCT 这个东西以前有写过 然而并不熟练 发现没了板子根本就不会写 只能填一填坑辣
1 #include <bits/stdc++.h> 2 #define N 30010 3 #define ls c[x][0] 4 #define rs c[x][1] 5 using namespace std; 6 7 inline int read() 8 { 9 int x=0,f=1; char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 12 return x*f; 13 } 14 int n,m,val[N]; 15 struct link_cut_tree 16 { 17 int c[N][2],fa[N],sum[N]; 18 bool rev[N]; 19 bool isroot(int x) 20 { 21 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 22 } 23 void updata(int x) 24 { 25 if(!x) return ; 26 sum[x]=sum[c[x][0]]+sum[c[x][1]]+val[x]; 27 } 28 void reverse(int x) 29 { 30 if(!x) return ; 31 rev[x]^=1; 32 swap(c[x][0],c[x][1]); 33 } 34 void pushdown(int x) 35 { 36 if(rev[x]) 37 { 38 reverse(c[x][0]); 39 reverse(c[x][1]); 40 rev[x]=0; 41 } 42 } 43 void rotate(int x) 44 { 45 int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1; 46 if(!isroot(y)) c[z][c[z][1]==y]=x; 47 if(c[x][r]) fa[c[x][r]]=y; 48 fa[y]=x;fa[x]=z; 49 c[y][l]=c[x][r];c[x][r]=y; 50 updata(y); updata(x); 51 } 52 void relax(int x) 53 { 54 if(!isroot(x)) relax(fa[x]); 55 pushdown(x); 56 } 57 void splay(int x) 58 { 59 relax(x); 60 while(!isroot(x)) 61 { 62 int y=fa[x],z=fa[y]; 63 if(!isroot(y)) 64 { 65 if((c[y][0]==x)^(c[z][0]==y)) rotate(y); 66 else rotate(x); 67 } 68 rotate(x); 69 } 70 } 71 void access(int x) 72 { 73 for(int p=0;x;p=x,x=fa[x]) 74 { 75 splay(x); c[x][1]=p; if(p) fa[p]=x; updata(x); 76 } 77 } 78 void makeroot(int x) 79 { 80 access(x); splay(x); 81 reverse(x); 82 } 83 void link(int x,int y) 84 { 85 makeroot(x); fa[x]=y; 86 } 87 int find(int x) 88 { 89 while(fa[x]) x=fa[x]; 90 return x; 91 } 92 int query(int x,int y) 93 { 94 makeroot(x); access(y); splay(y); 95 return sum[y]; 96 } 97 }T; 98 int main() 99 { 100 //freopen("read.in","r",stdin); 101 //freopen("wro.out","w",stdout); 102 n=read();for(int i=1;i<=n;i++) val[i]=read(); 103 m=read();while(m--) 104 { 105 char sd[100]; scanf("%s",sd); 106 int u=read(),v=read(); 107 if(sd[0]=='e') 108 { 109 if(T.find(u)==T.find(v)) 110 printf("%d\n",T.query(u,v)); 111 else printf("impossible\n"); 112 } 113 if(sd[0]=='b') 114 { 115 if(T.find(u)==T.find(v)) 116 printf("no\n"); 117 else T.link(u,v),printf("yes\n"); 118 } 119 if(sd[0]=='p') 120 { 121 val[u]=v; T.access(u); 122 } 123 } 124 return 0; 125 }
LCT? 我是先用离线的树链剖分先A了这题 发现LCT 实现起来比树剖更短 而且稍快(但是你一个log(LCT) 跟 人家俩log(树剖)跑得差不多 是不是不太好)
不在意。。QAQ
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 inline int read() 6 { 7 int x=0,f=1;char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 10 return x*f; 11 } 12 int st[30010],ee; 13 struct edge 14 { 15 int u,v,next; 16 }vs[60010]; 17 int vl[30010],Fa[30010],lastadd; 18 struct que 19 { 20 int dps; 21 int u,v,tp; 22 }Q[100010]; 23 int getfa(int x){return (Fa[x]==x)? x: Fa[x]=getfa(Fa[x]);} 24 inline void addedge(int u,int v) 25 { 26 vs[++ee].v=v;vs[ee].u=u;vs[ee].next=st[u];st[u]=ee; 27 } 28 int fa[30010],dep[30010],size[30010],son[30010],top[30010]; 29 int pl[30010],bl[30010],tree[30010<<2],n,m,vis[30010]; 30 void dfs1(int rt) 31 { 32 size[rt]=1; vis[rt]=1; 33 for(int i=st[rt];i;i=vs[i].next) 34 { 35 if(fa[rt]==vs[i].v) continue; 36 fa[vs[i].v]=rt; 37 dep[vs[i].v]=dep[rt]+1; 38 dfs1(vs[i].v); 39 if(size[son[rt]]<size[vs[i].v]) 40 son[rt]=vs[i].v; 41 } 42 } 43 void dfs2(int rt) 44 { 45 pl[rt]=++lastadd; bl[lastadd]=rt; 46 vis[rt]=1; 47 if(son[rt]) 48 { 49 top[son[rt]]=top[rt]; 50 dfs2(son[rt]); 51 } 52 for(int i=st[rt];i;i=vs[i].next) 53 { 54 if(fa[rt]==vs[i].v||vs[i].v==son[rt]) continue; 55 dfs2(vs[i].v); 56 } 57 } 58 inline void updata(int rt) 59 { 60 tree[rt]=tree[rt<<1]+tree[rt<<1|1]; 61 } 62 void built(int l,int r,int rt) 63 { 64 if(l==r) 65 { 66 tree[rt]=vl[bl[l]]; 67 return ; 68 } 69 int mid=(l+r)>>1; 70 built(l,mid,rt<<1); built(mid+1,r,rt<<1|1); 71 updata(rt); 72 } 73 int query(int L,int R,int l,int r,int rt) 74 { 75 if(L<=l&&r<=R) return tree[rt]; 76 int mid=(l+r)>>1; 77 if(mid>=R) return query(L,R,l,mid,rt<<1); 78 if(mid<L) return query(L,R,mid+1,r,rt<<1|1); 79 return query(L,R,l,mid,rt<<1)+query(L,R,mid+1,r,rt<<1|1); 80 } 81 void modify(int x,int y,int l,int r,int rt) 82 { 83 if(l==r) 84 { 85 tree[rt]=y; 86 return ; 87 } 88 int mid=(l+r)>>1; 89 if(mid>=x) modify(x,y,l,mid,rt<<1); 90 else modify(x,y,mid+1,r,rt<<1|1); 91 updata(rt); 92 } 93 inline int cal(int u,int v) 94 { 95 int ans=0; 96 int f1=top[u],f2=top[v]; 97 if(dep[f1]>dep[f2]) swap(u,v),swap(f1,f2); 98 while(f1!=f2) 99 { 100 ans+=query(pl[f2],pl[v],1,n,1); 101 v=fa[f2]; f2=top[v]; 102 if(dep[f1]>dep[f2]) swap(u,v),swap(f1,f2); 103 } 104 if(dep[u]>dep[v]) swap(u,v); 105 ans+=query(pl[u],pl[v],1,n,1); 106 return ans; 107 } 108 int main() 109 { 110 //freopen("read.in","r",stdin); 111 //freopen("wro.out","w",stdout); 112 n=read(); 113 for(int i=1;i<=n;i++) vl[i]=read(),Fa[i]=i; 114 m=read(); 115 for(int i=1;i<=m;i++) 116 { 117 char sd[1000]; 118 scanf("%s",sd); 119 int u=read(),v=read(); 120 if(sd[0]=='e') 121 { 122 Q[i].dps=1; Q[i].tp=0; 123 if(getfa(u)!=getfa(v)) 124 Q[i].tp=1; 125 } 126 else if(sd[0]=='b') 127 { 128 Q[i].dps=2; 129 int f1=getfa(u),f2=getfa(v); 130 if(f1!=f2) 131 { 132 Q[i].tp=1; 133 Fa[f1]=f2; 134 addedge(u,v);addedge(v,u); 135 } 136 } 137 else Q[i].dps=3; 138 Q[i].u=u; Q[i].v=v; 139 } 140 for(int i=1;i<=n;i++) top[i]=i; 141 //dfs1(1); dfs2(1); 142 for(int i=1;i<=n;i++) if(!vis[i]) dfs1(i); 143 memset(vis,0,sizeof vis); 144 for(int i=1;i<=n;i++) if(!vis[i]) dfs2(i); 145 built(1,n,1); 146 for(int i=1;i<=m;i++) 147 { 148 if(Q[i].dps==2) 149 { 150 if(Q[i].tp==1) printf("yes\n"); 151 else printf("no\n"); 152 } 153 else if(Q[i].dps==1) 154 { 155 if(Q[i].tp==1) printf("impossible\n"); 156 else printf("%d\n",cal(Q[i].u,Q[i].v)); 157 } 158 else if(Q[i].dps==3) 159 modify(pl[Q[i].u],Q[i].v,1,n,1); 160 } 161 return 0; 162 }
注意点:: LCT中 0号节点也会用于更新树的值 要时刻维护其fa、c为0 否则就会爆掉!! 感谢 Cicada
例:
1 void rotate(int x) 2 { 3 int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1; 4 if(!isroot(y)) c[z][c[z][1]==y]=x; 5 if(c[x][r])/*!!!*/ fa[c[x][r]]=y; /* EXCITING!!*/ 6 fa[y]=x;fa[x]=z; 7 c[y][l]=c[x][r];c[x][r]=y; 8 updata(y); updata(x); 9 }
1 #include <bits/stdc++.h> 2 #define ls c[x][0] 3 #define rs c[x][1] 4 #define inf 0x7fffffff 5 using namespace std; 6 7 inline int read() 8 { 9 int x=0,f=1; char ch=getchar(); 10 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 12 return x*f; 13 } 14 struct events 15 { 16 int u,v,start,end; 17 }E[200010]; 18 struct Mt 19 { 20 int bl,tp; 21 }Gs[400010]; 22 int sign[200010],tot; 23 inline int timcatch(Mt a) 24 { 25 return (a.tp==1)? E[a.bl].start: E[a.bl].end; 26 } 27 inline bool cmp(const Mt a,const Mt b) 28 { 29 return timcatch(a)==timcatch(b)? a.tp<b.tp:timcatch(a)<timcatch(b); 30 } 31 int n,m,tt,mxx,val[400010]; 32 struct link_cut_tree 33 { 34 int mi[400010],sum[400010],vl[400010]; 35 int c[400010][2],fa[400010],rev[400010]; 36 inline bool isroot(int x) 37 { 38 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 39 } 40 inline void updata(int x) 41 { 42 mi[x]=x; sum[x]=1; 43 if(ls) 44 { 45 if(val[mi[x]]>val[mi[ls]]) mi[x]=mi[ls]; 46 sum[x]+=sum[ls]; 47 } 48 if(rs) 49 { 50 if(val[mi[x]]>val[mi[rs]]) mi[x]=mi[rs]; 51 sum[x]+=sum[rs]; 52 } 53 } 54 void rever(int x) 55 { 56 if(!x) return ; 57 rev[x]^=1; swap(ls,rs); 58 } 59 void pushdown(int x) 60 { 61 if(rev[x]) 62 { 63 rever(ls); rever(rs); 64 rev[x]^=1; 65 } 66 } 67 void rotate(int x) 68 { 69 int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1; 70 if(!isroot(y)) c[z][c[z][1]==y]=x; 71 if(c[x][r]) fa[c[x][r]]=y; 72 fa[y]=x; fa[x]=z; 73 c[y][l]=c[x][r]; c[x][r]=y; 74 updata(y); updata(x); 75 } 76 void relax(int x) 77 { 78 if(!isroot(x)) relax(fa[x]); 79 pushdown(x); 80 } 81 void splay(int x) 82 { 83 relax(x); 84 while(!isroot(x)) 85 { 86 int y=fa[x],z=fa[y]; 87 if(!isroot(y)) 88 { 89 if((c[y][0]==x)^(c[z][0]==y)) rotate(y); 90 else rotate(x); 91 } 92 rotate(x); 93 } 94 } 95 void access(int x) 96 { 97 for(int p=0;x;p=x,x=fa[x]) 98 { 99 splay(x); c[x][1]=p; 100 if(p) fa[p]=x; 101 updata(x); 102 } 103 } 104 void makeroot(int x) 105 { 106 access(x); splay(x); rever(x); 107 } 108 void link(int x,int y) 109 { 110 makeroot(x); fa[x]=y; 111 } 112 void cut(int x,int y) 113 { 114 makeroot(x); access(y);splay(y); 115 c[y][0]=fa[x]=0; 116 } 117 118 int find(int x) 119 { 120 while(fa[x]) x=fa[x]; return x; 121 } 122 void insert(int x) 123 { 124 sign[x]=1; link(E[x].u,x+n); link(E[x].v,x+n); 125 } 126 void delet(int x) 127 { 128 sign[x]=0; cut(E[x].u,x+n); cut(E[x].v,x+n); 129 } 130 void flod(int x,int y,int t) 131 { 132 makeroot(x); access(y);splay(y); 133 if((sum[y]>>1)&1) delet(mi[y]-n),insert(t); 134 else 135 { 136 int x=mi[y]; 137 if(val[x]>val[t+n]) mxx=max(mxx,val[t+n]); 138 else mxx=max(mxx,val[x]),delet(mi[y]-n),insert(t); 139 } 140 } 141 }T; 142 143 void doin(int x) 144 { 145 if(Gs[x].tp==-1&&sign[Gs[x].bl]) 146 T.delet(Gs[x].bl); 147 if(Gs[x].tp==1&&!sign[Gs[x].bl]) 148 { 149 if(T.find(E[Gs[x].bl].u)!=T.find(E[Gs[x].bl].v)) 150 T.insert(Gs[x].bl); 151 else T.flod(E[Gs[x].bl].u,E[Gs[x].bl].v,Gs[x].bl); 152 } 153 } 154 int main() 155 { 156 //freopen("read.in","r",stdin); 157 //freopen("wro.out","w",stdout); 158 n=read();m=read();tt=read(); 159 for(int i=1;i<=n;i++) val[i]=inf; 160 for(int i=1;i<=m;i++) 161 { 162 E[i].u=read();E[i].v=read(); 163 E[i].start=read(); 164 E[i].end=read(); 165 Gs[++tot].bl=i; Gs[tot].tp=1; 166 Gs[++tot].bl=i; Gs[tot].tp=-1; 167 val[i+n]=E[i].end; 168 } 169 sort(Gs+1,Gs+1+tot,cmp); 170 /* for(int i=1;i<=tot;i++) 171 { 172 printf("%d %d %d %d\n",E[Gs[i].bl].u,E[Gs[i].bl].v,Gs[i].tp,timcatch(Gs[i])); 173 } */ 174 for(int i=1,j=1;i<=tt;i++) 175 { 176 while(timcatch(Gs[j])<i&&j<=tot) doin(j),j++; 177 //printf("%d ",mxx); 178 if(mxx>=i) printf("No\n"); 179 else printf("Yes\n"); 180 } 181 }
感谢 GhostReach
发现当图中存在奇环时 就不再是二分图 那么在LCT上维护两个信息 边消失的时间 以及 从一个点到另一个点的距离
每次按出现的时间顺序加入一条边
1、 边的两个顶点 在两颗不同的树中—— 直接link
2、 边的两个顶点 在同一颗树中
(i)加入后形成奇环—— 更新‘no’ 持续的时间 并删去 环上 消失时间最早的边
(ii)加入后形成偶环—— 直接删去 环上消失时间最早的边
ps:LCT的信息在边上 新开点维护
1 #include <bits/stdc++.h> 2 #define ls c[x][0] 3 #define rs c[x][1] 4 using namespace std; 5 typedef long long ll; 6 inline int read() 7 { 8 int x=0,f=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 11 return x*f; 12 } 13 int n,m; 14 ll val[50010]; 15 ll gcd(ll a,ll b) 16 { 17 return (a%b)? gcd(b,a%b): b; 18 } 19 struct link_cut_tree 20 { 21 int fa[50010],c[50010][2],add[50010]; 22 ll sum1[50010],sum2[50010],sumE1[50010],sumE2[50010],sumP[50010],sumV[50010]; 23 bool rev[50010]; 24 inline bool isroot(int x) 25 { 26 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 27 } 28 void reverse(int x) 29 { 30 if(!x) return ; 31 rev[x]^=1; swap(ls,rs); 32 swap(sum2[x],sum1[x]); 33 swap(sumE1[x],sumE2[x]); 34 } 35 void adds(int x,int y) 36 { 37 if(!x) return; 38 sumV[x]+=sumP[x]*y; 39 sum1[x]+=y*(sumP[x]+1)*sumP[x]/2; 40 sum2[x]+=y*(sumP[x]+1)*sumP[x]/2; 41 sumE1[x]+=((sumP[x]+1)*(sumP[x]+1)*(sumP[x])/2-(sumP[x]*2+1)*(sumP[x]+1)*(sumP[x])/6)*y; 42 sumE2[x]+=((sumP[x]+1)*(sumP[x]+1)*(sumP[x])/2-(sumP[x]*2+1)*(sumP[x]+1)*(sumP[x])/6)*y; 43 val[x]+=y;add[x]+=y; 44 } 45 void pushdown(int x) 46 { 47 if(!x) return ; 48 if(add[x]) 49 { 50 adds(ls,add[x]); adds(rs,add[x]); add[x]=0; 51 } 52 if(rev[x]) 53 { 54 reverse(ls); reverse(rs); rev[x]^=1; 55 } 56 } 57 void updata(int x) 58 { 59 if(!x) return ; 60 sumP[x]=1; 61 if(ls) sumP[x]+=sumP[ls]; 62 if(rs) sumP[x]+=sumP[rs]; 63 sumV[x]=val[x]; 64 if(ls) sumV[x]+=sumV[ls]; 65 if(rs) sumV[x]+=sumV[rs]; 66 sum1[x]=(sumP[ls]+1)*val[x]; 67 if(ls) sum1[x]+=sum1[ls]; 68 if(rs) sum1[x]+=(sumV[rs]*(sumP[ls]+1))+sum1[rs]; 69 sum2[x]=(sumP[rs]+1)*val[x]; 70 if(ls) sum2[x]+=(sumV[ls]*(sumP[rs]+1))+sum2[ls]; 71 if(rs) sum2[x]+=sum2[rs]; 72 sumE1[x]=val[x]*(sumP[ls]+1)*(sumP[rs]+1); 73 if(ls) sumE1[x]+=sumE1[ls]+sum1[ls]*(sumP[rs]+1); 74 if(rs) sumE1[x]+=sumE1[rs]+sum2[rs]*(sumP[ls]+1); 75 sumE2[x]=val[x]*(sumP[ls]+1)*(sumP[rs]+1); 76 if(ls) sumE2[x]+=sumE2[ls]+sum1[ls]*(sumP[rs]+1); 77 if(rs) sumE2[x]+=sumE2[rs]+sum2[rs]*(sumP[ls]+1); 78 } 79 void relax(int x) 80 { 81 if(!isroot(x)) relax(fa[x]); 82 pushdown(x); 83 } 84 void rotate(int x) 85 { 86 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 87 if(!isroot(y)) c[z][c[z][1]==y]=x; 88 if(c[x][r]) fa[c[x][r]]=y; 89 fa[x]=z; fa[y]=x; 90 c[y][l]=c[x][r]; c[x][r]=y; 91 updata(y); updata(x); 92 } 93 void splay(int x) 94 { 95 relax(x); 96 while(!isroot(x)) 97 { 98 int y=fa[x],z=fa[y]; 99 if(!isroot(y)) 100 { 101 if((c[y][0]==x)^(c[z][0]==y)) rotate(y); 102 else rotate(x); 103 } 104 rotate(x); 105 } 106 } 107 void access(int x) 108 { 109 for(int p=0;x;p=x,x=fa[x]) 110 { 111 splay(x); c[x][1]=p; if(p) fa[p]=x; updata(x); 112 } 113 } 114 void makeroot(int x) 115 { 116 access(x); splay(x); reverse(x); 117 } 118 int find(int x) 119 { 120 while(fa[x]) x=fa[x]; 121 return x; 122 } 123 void link(int x,int y) 124 { 125 makeroot(x); fa[x]=y; 126 } 127 void cut(int x,int y) 128 { 129 makeroot(x); access(y); splay(y); 130 if(sumP[y]!=2) return; 131 c[y][0]=fa[x]=0; 132 updata(y); 133 } 134 void addval(int x,int y,int z) 135 { 136 makeroot(x); access(y); splay(y); 137 adds(y,z); 138 } 139 void query(int x,int y) 140 { 141 makeroot(x); access(y); splay(y); 142 ll tmp=gcd(sumE2[y],sumP[y]*(sumP[y]+1)>>1); 143 printf("%lld/%lld\n",sumE2[y]/tmp,(sumP[y]*(sumP[y]+1)>>1)/tmp); 144 } 145 }T; 146 int main() 147 { 148 //freopen("read.in","r",stdin); 149 //freopen("wro.in","w",stdout); 150 n=read();m=read(); 151 for(int i=1;i<=n;i++) val[i]=read(); 152 for(int i=1;i<n;i++) 153 { 154 int u=read(),v=read(); 155 T.link(u,v); 156 } 157 for(int i=1;i<=m;i++) 158 { 159 int tp=read(); 160 if(tp==1) 161 { 162 int u=read(),v=read(); 163 if(T.find(u)!=T.find(v)) continue; 164 T.cut(u,v); 165 } 166 if(tp==2) 167 { 168 int u=read(),v=read(); 169 if(T.find(u)==T.find(v)) continue; 170 T.link(u,v); 171 } 172 if(tp==3) 173 { 174 int u=read(),v=read(),z=read(); 175 if(T.find(u)!=T.find(v)) continue; 176 T.addval(u,v,z); 177 } 178 if(tp==4) 179 { 180 int u=read(),v=read(); 181 if(T.find(u)!=T.find(v)) printf("-1\n"); 182 else T.query(u,v); 183 } 184 } 185 }
需要推一点点式子
ps: 我好naive啊 lct上打标记的技巧 好像有点神奇啊 感谢:AwD
打标记:
1 void do_with_tag(** **,** **) 2 { 3 **********//do anything you like 4 make_tag_with_ls; 5 make_tag_with_rs; 6 } 7 void pushdown(** **) 8 { 9 if(there_is_tag) 10 { 11 do_with_tag(ls); 12 do_with_tag(rs); 13 delete_the_tag; 14 } 15 } 16 //这里的tag 是这个节点上有信息需要被下传 17 //跟我以前打过的标记都不一样QAQ 坑了好久
这题的dmk
1 #include <bits/stdc++.h> 2 #define N 50000 3 #define M 50000 4 using namespace std; 5 6 int main() 7 { 8 freopen("read.in","w",stdout); 9 srand(time(0)); 10 printf("%d\n",N);printf("%d\n",M); 11 for(int i=1;i<=N;i++) printf("%d ",rand()*rand()%1000000); printf("\n"); 12 for(int i=2;i<=N;i++) 13 { 14 int x=rand()%(i-1)+1; 15 printf("%d %d\n",i,x); 16 } 17 18 for(int i=1;i<=M;i++) 19 { 20 int tx=rand()%4+1; printf("%d ",tx); 21 if(tx==1||tx==2||tx==4) printf("%d %d\n",rand()%N+1,rand()%N+1); 22 if(tx==3) printf("%d %d %d\n",rand()%N+1,rand()%N+1,rand()*rand()%1000000); 23 } 24 }
1 #include <bits/stdc++.h> 2 #define inf 0x7fffffff 3 #define ls c[x][0] 4 #define rs c[x][1] 5 #define int long long 6 using namespace std; 7 8 inline int read() 9 { 10 int x=0,f=1; char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 int n,val[60010],m; 16 struct link_cut_tree 17 { 18 int c[60010][2],fa[60010]; 19 int mx[60010],mi[60010],sum[60010],rev[60010],tbk[60010]; 20 inline bool isroot(int x) 21 { 22 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 23 } 24 inline void updata(int x) 25 { 26 if(!x) return; 27 mx[x]=max(mx[ls],mx[rs]); 28 mi[x]=min(mi[ls],mi[rs]); 29 if(x>n)mx[x]=max(mx[x],val[x]); 30 if(x>n)mi[x]=min(mi[x],val[x]); 31 sum[x]=sum[ls]+sum[rs]+val[x]; 32 } 33 inline void reverse(int x) 34 { 35 if(!x) return ; 36 rev[x]^=1; swap(ls,rs); 37 } 38 inline void turnback(int x) 39 { 40 if(!x) return; 41 sum[x]=-sum[x];val[x]=-val[x]; 42 swap(mi[x],mx[x]); 43 mi[x]=-mi[x];mx[x]=-mx[x]; 44 tbk[x]^=1; 45 } 46 inline void pushdown(int x) 47 { 48 if(!x) return ; 49 if(rev[x]) 50 { 51 reverse(ls); reverse(rs); rev[x]^=1; 52 } 53 if(tbk[x]) 54 { 55 tbk[x]=0; turnback(ls); turnback(rs); 56 } 57 } 58 void relax(int x) 59 { 60 if(!isroot(x)) relax(fa[x]); 61 pushdown(x); 62 } 63 void rotate(int x) 64 { 65 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 66 if(!isroot(y)) c[z][c[z][1]==y]=x; 67 if(c[x][r]) fa[c[x][r]]=y; 68 fa[x]=z; fa[y]=x; 69 c[y][l]=c[x][r]; c[x][r]=y; 70 updata(y); updata(x); 71 } 72 void splay(int x) 73 { 74 relax(x); 75 while(!isroot(x)) 76 { 77 int y=fa[x],z=fa[y]; 78 if(!isroot(y)) 79 { 80 if((c[y][0]==x)^(c[z][0]==y)) rotate(y); 81 else rotate(x); 82 } 83 rotate(x); 84 } 85 } 86 void access(int x) 87 { 88 for(int p=0;x;p=x,x=fa[x]) 89 { 90 splay(x); c[x][1]=p; if(p) fa[p]=x; updata(x); 91 } 92 } 93 void makeroot(int x) 94 { 95 access(x); splay(x); reverse(x); 96 } 97 void modify1(int x,int y) 98 { 99 makeroot(x); access(x); splay(x); 100 val[x]=y; updata(x); 101 } 102 void modify2(int x,int y) 103 { 104 makeroot(x); access(y); splay(y); 105 turnback(y); 106 } 107 inline void query(int x,int y,int tp) 108 { 109 makeroot(x); access(y); splay(y); 110 if(tp==1) printf("%lld\n",mi[y]); 111 if(tp==2) printf("%lld\n",mx[y]); 112 if(tp==3) printf("%lld\n",sum[y]); 113 } 114 inline void link(int x,int y) 115 { 116 makeroot(x); fa[x]=y; 117 } 118 }T; 119 signed main() 120 { 121 //freopen("read.in","r",stdin); 122 //freopen("wro.in","w",stdout); 123 n=read(); 124 T.mx[0]=-inf; T.mi[0]=inf; 125 for(int i=1;i<n;i++) 126 { 127 T.mx[i]=-inf; 128 T.mi[i]=inf; 129 int u=read()+1,v=read()+1,w=read(); 130 T.link(u,i+n); T.link(v,i+n); 131 T.mx[i+n]=T.mi[i+n]=T.sum[i+n]=val[i+n]=w; 132 } 133 m=read(); 134 for(int i=1;i<=m;i++) 135 { 136 char sd[10]; scanf("%s",sd); 137 int u=read(),v=read(); 138 if(sd[0]=='S') T.query(u+1,v+1,3); 139 if(sd[0]=='M'&&sd[1]=='I') T.query(u+1,v+1,1); 140 if(sd[0]=='M'&&sd[1]=='A') T.query(u+1,v+1,2); 141 if(sd[0]=='N') T.modify2(u+1,v+1); 142 if(sd[0]=='C') T.modify1(u+n,v); 143 //for(int j=n+1;j<=n+n-1;j++) printf("%d ",val[j]); 144 } 145 }
生无可恋QAQ 这种题。。。。WA了一个多小时
还是维护信息时要仔细
1 #include <bits/stdc++.h> 2 #define ls c[x][0] 3 #define rs c[x][1] 4 using namespace std; 5 6 inline int read() 7 { 8 int x=0,f=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 11 return x*f; 12 } 13 int n,m,c,k,val[10010],colnum[10010][11]; 14 map <int,int> M[10010]; 15 struct link_cut_tree 16 { 17 int fa[10010],c[10010][2],mx[10010],sz[10010]; 18 bool rev[10010]; 19 inline bool isroot(int x) 20 { 21 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 22 } 23 void reverse(int x) 24 { 25 if(!x) return ; 26 rev[x]^=1; swap(ls,rs); 27 } 28 void pushdown(int x) 29 { 30 if(!x) return ; 31 if(rev[x]) 32 { 33 reverse(ls); reverse(rs); rev[x]^=1; 34 } 35 } 36 void updata(int x) 37 { 38 if(!x) return ; 39 mx[x]=val[x];sz[x]=1; 40 if(ls) mx[x]=max(mx[x],mx[ls]),sz[x]+=sz[ls]; 41 if(rs) mx[x]=max(mx[x],mx[rs]),sz[x]+=sz[rs]; 42 } 43 void relax(int x) 44 { 45 if(!isroot(x)) relax(fa[x]); 46 pushdown(x); 47 } 48 void rotate(int x) 49 { 50 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 51 if(!isroot(y)) c[z][c[z][1]==y]=x; 52 if(c[x][r]) fa[c[x][r]]=y; 53 fa[x]=z; fa[y]=x; 54 c[y][l]=c[x][r]; c[x][r]=y; 55 updata(y); updata(x); 56 } 57 void splay(int x) 58 { 59 relax(x); 60 while(!isroot(x)) 61 { 62 int y=fa[x],z=fa[y]; 63 if(!isroot(y)) 64 { 65 if((c[y][0]==x)^(c[z][0]==y)) rotate(y); 66 else rotate(x); 67 } 68 rotate(x); 69 } 70 } 71 void access(int x) 72 { 73 for(int p=0;x;p=x,x=fa[x]) 74 { 75 splay(x); c[x][1]=p; if(p) fa[p]=x; updata(x); 76 } 77 } 78 void makeroot(int x) 79 { 80 access(x); splay(x); reverse(x); 81 } 82 int find(int x) 83 { 84 while(fa[x]) x=fa[x]; 85 return x; 86 } 87 void link(int x,int y) 88 { 89 makeroot(x); fa[x]=y; 90 } 91 int cut(int x,int y) 92 { 93 makeroot(x); access(y); splay(y); 94 if(sz[y]!=2) return 0; 95 c[y][0]=fa[x]=0; 96 updata(y); 97 return 1; 98 } 99 void addval(int x,int z) 100 { 101 splay(x); 102 val[x]=z; mx[x]=z; updata(x); 103 } 104 void query(int x,int y) 105 { 106 makeroot(x); access(y); splay(y); 107 printf("%d\n",mx[y]); 108 } 109 }T[11]; 110 111 int main() 112 { 113 //freopen("read.in","r",stdin); 114 //freopen("wro.in","w",stdout); 115 n=read();m=read();c=read();k=read(); 116 for(int i=1;i<=n;i++) val[i]=read(); 117 for(int i=1;i<=m;i++) 118 { 119 int u=read(),v=read(),w=read()+1; 120 T[w].link(u,v); 121 M[u][v]=w; M[v][u]=w; 122 colnum[u][w]++; 123 colnum[v][w]++; 124 } 125 for(int i=1;i<=k;i++) 126 { 127 int tp=read(),x=read(),y=read(); 128 if(tp==0) for(int j=1;j<=c;j++) T[j].addval(x,y); 129 if(tp==1) 130 { 131 int g=M[x][y],kg=read()+1; 132 if(!g) {printf("No such edge.\n"); continue;} 133 if(g==kg){printf("Success.\n"); continue;} 134 if(colnum[x][kg]>=2||colnum[y][kg]>=2) 135 { 136 printf("Error 1.\n"); continue; 137 } 138 if(T[kg].find(x)==T[kg].find(y)) 139 { 140 printf("Error 2.\n"); continue; 141 } 142 printf("Success.\n"); 143 T[g].cut(x,y); T[kg].link(x,y); 144 M[x][y]=kg; M[y][x]=kg; 145 colnum[x][g]--;colnum[y][g]--; 146 colnum[x][kg]++; colnum[y][kg]++; 147 } 148 if(tp==2) 149 { 150 int g=read(); x++; 151 if(T[x].find(g)!=T[x].find(y)) 152 printf("-1\n"); 153 else T[x].query(g,y); 154 } 155 } 156 return 0; 157 }
多种颜色 于是维护10棵LCT 暴力去修改 冷静地开10000个MAP (假装不会出事)这种做法讲讲道理是可以被卡掉的QAQ
ps: 为什么我的LCT 常数这么大
1 #include <bits/stdc++.h> 2 #define N 30010 3 #define ls c[x][0] 4 #define rs c[x][1] 5 #define mod 10007 6 using namespace std; 7 typedef long long ll; 8 inline int read() 9 { 10 int x=0,f=1; char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} 13 return x*f; 14 } 15 int exgcd(int a,int b,int &x,int &y) 16 { 17 if(b==0){x=1;y=0;return a;} 18 int r=exgcd(b,a%b,x,y); 19 int t=x;x=y; y=t-a/b*y; 20 return r; 21 } 22 inline int inv(int x) 23 { 24 int X,Y; exgcd((x%mod+mod)%mod,mod,X,Y); 25 return (X%mod+mod)%mod; 26 } 27 int n,m,fa[N],vis[N],tim; 28 struct link_cut_tree 29 { 30 int fa[N],c[N][2],k[N],b[N],sf[N],rev[N]; 31 struct fcl 32 { 33 int k,b; 34 int f(int x){return (k*x+b)%mod;} 35 }sum[N],val[N]; 36 friend fcl operator+(fcl a,fcl b) 37 { 38 fcl tmp; 39 tmp.k=(a.k*b.k)%mod; 40 tmp.b=(b.b+b.k*a.b%mod)%mod; 41 return tmp; 42 } 43 inline bool isroot(int x) 44 { 45 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 46 } 47 inline void updata(int x) 48 { 49 if(!x) return; 50 sum[x]=val[x]; 51 if(ls) sum[x]=sum[ls]+sum[x]; 52 if(rs) sum[x]=sum[x]+sum[rs]; 53 } 54 void rotate(int x) 55 { 56 int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; 57 if(!isroot(y)) c[z][c[z][1]==y]=x; 58 if(c[x][r]) fa[c[x][r]]=y; 59 fa[x]=z; fa[y]=x; 60 c[y][l]=c[x][r]; c[x][r]=y; 61 updata(y); updata(x); 62 } 63 void splay(int x) 64 { 65 while(!isroot(x)) 66 { 67 int y=fa[x],z=fa[y]; 68 if(!isroot(y)) 69 { 70 if((c[z][0]==y)^(c[y][0]==x)) rotate(y); 71 else rotate(x); 72 } 73 rotate(x); 74 } 75 } 76 void access(int x) 77 { 78 for(int p=0;x;p=x,x=fa[x]) 79 { 80 splay(x); c[x][1]=p; if(p) fa[p]=x; updata(x); 81 } 82 } 83 inline int findroot(int x) 84 { 85 access(x); splay(x); 86 while(c[x][0]) x=c[x][0]; 87 return x; 88 } 89 void modify() 90 { 91 int x=read(),k=read(),p=read(),b=read(); 92 val[x].k=k; val[x].b=b; 93 int t=findroot(x); 94 if(t==x) sf[x]=0; 95 else 96 { 97 access(x); splay(x); 98 fa[c[x][0]]=0;c[x][0]=0; 99 updata(x); 100 if(findroot(sf[t])!=t) 101 { 102 access(t); splay(t); 103 fa[t]=sf[t]; 104 sf[t]=0; 105 } 106 } 107 access(x); splay(x); 108 if(findroot(p)==x) 109 sf[x]=p; 110 else fa[x]=p; 111 } 112 int query() 113 { 114 int x=read(),t=findroot(x); 115 access(sf[t]); splay(sf[t]); 116 int k=sum[sf[t]].k; 117 int b=sum[sf[t]].b; 118 //printf("%d %d\n",k,b); 119 if(k==1) 120 { 121 if(b==0) return -2; 122 else return -1; 123 } 124 //printf("%d\n",inv(k-1)); 125 int tmp=(-b+mod)*inv(k-1)%mod; 126 //printf("%d\n",tmp); 127 access(x); splay(x); 128 return sum[x].f(tmp); 129 } 130 }T; 131 void dfs(int x) 132 { 133 vis[x]=tim; 134 if(vis[fa[x]]==tim) 135 { 136 T.sf[x]=fa[x]; 137 return; 138 } 139 T.fa[x]=fa[x]; 140 if(!vis[T.fa[x]]) dfs(T.fa[x]); 141 } 142 int main() 143 { 144 //freopen("read.in","r",stdin); 145 n=read(); 146 for(int i=1;i<=n;i++) 147 T.val[i].k=read(),fa[i]=read(),T.val[i].b=read(),T.sum[i]=T.val[i]; 148 for(int i=1;i<=n;i++) 149 if(!vis[i]) ++tim,dfs(i); 150 m=read(); 151 //for(int i=1;i<=n;i++) printf("%d ",T.fa[i]); printf("\n"); 152 //for(int i=1;i<=n;i++) printf("%d ",T.sf[i]); printf("\n"); 153 while(m--) 154 { 155 char sd[4]; 156 scanf("%s",sd); 157 if(sd[0]=='A') printf("%d\n",T.query()); 158 if(sd[0]=='C') T.modify(); 159 } 160 return 0; 161 }
一道LCT好题 题如其名 真的是道好题 就可惜我不会做QAQ
由于是一个基环树 对于一个环 可以把一条环边拆开 对于 这条边的起点 记录一个特殊的父亲
那么 对于一个询问 先将环上的边exciting出来 然后在 拿来更新询问的点 所在的链 答案就可以出来了
1 int query() 2 { 3 int x=read(),t=findroot(x); 4 access(sf[t]); splay(sf[t]); 5 int k=sum[sf[t]].k; 6 int b=sum[sf[t]].b; 7 //printf("%d %d\n",k,b); 8 if(k==1) 9 { 10 if(b==0) return -2; 11 else return -1; 12 } 13 //printf("%d\n",inv(k-1)); 14 int tmp=(-b+mod)*inv(k-1)%mod; 15 //printf("%d\n",tmp); 16 access(x); splay(x); 17 return sum[x].f(tmp); 18 }
ps: 维护答案的k 和 b 要注意ls rs 不要打反 holyshit 1hour+