2959: 长跑|LCT+并查集
Posted ws_yzy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2959: 长跑|LCT+并查集相关的知识,希望对你有一定的参考价值。
慎入…此人代码自带5倍常数。。
静态的话就是随便搞出一棵生成树来,然后把环缩起来,询问的答案就是路径上的权值和
动态的就需要LCT来维护生成树,每遇到连起边来就形成环的情况时,就把这个环缩成一个点
动态的查询一条链上的权值和。
为什么我的代码的常数这么大…….后几个点在本地跑5s
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<ctime>
#include<queue>
#include<set>
#include<map>
#define q1 Q[T^1]
#define q2 Q[T]
#define N 1000005
using namespace std;
long long sum[N],v[N];
bool rev[N];
int fa[N],ch[N][2],n,m,dad[N],st[N];
int find(int x)
return dad[x]==x?x:dad[x]=find(dad[x]);
void push_down(int x)
if(rev[x])
swap(ch[x][0],ch[x][1]);
rev[ch[x][0]]^=1;
rev[ch[x][1]]^=1;
rev[x]=0;
void push_up(int x)
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+v[x];
bool Root(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;
l=(ch[y][1]==x);r=l^1;
if(!Root(y)) ch[z][ch[z][1]==y]=x;
ch[y][l]=ch[x][r]; ch[x][r]=y;
fa[ch[y][l]]=y;fa[y]=x;fa[x]=z;
push_up(y); push_up(x);
void splay(int x)
int top=0;st[++top]=x;
for(int i=x;!Root(i);i=fa[i])st[++top]=fa[i];
while(top)push_down(st[top--]);
while(!Root(x))
int y=fa[x],z=fa[y];
if(!Root(y))
if(ch[z][0]==y^ch[y][0]==x)
rotate(x);
else rotate(y);
rotate(x);
void access(int x)
for(int t=0;x;t=x,x=find(fa[x]))
splay(x),ch[x][1]=t,push_up(x);
if(t)fa[t]=x;
void make_root(int x)
access(x),splay(x),rev[x]^=1;
void link(int x,int y)
make_root(x),fa[x]=y;
int search(int x)
access(x);splay(x);
while(ch[x][0])x=ch[x][0],push_down(x);
return x;
void dfs(int x,int f)
if(!x)return;
dad[x]=f;
dfs(ch[x][0],f);
dfs(ch[x][1],f);
void merge(int x,int y)
make_root(x),access(y),splay(y);
++n;dad[n]=n;
sum[n]=v[n]=sum[y];
dfs(y,n);
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&v[i]),dad[i]=i;
while(m--)
int opt,x,y;
scanf("%d%d%d",&opt,&x,&y);
if(opt==1)
if(find(x)!=find(y))
x=find(x),y=find(y);
if(search(x)!=search(y))
link(x,y);
else merge(x,y);
else if(opt==2)
int ch=y-v[x];
int F=find(x);
access(F),splay(F);
v[F]+=ch,sum[F]+=ch;
v[x]=y;
else
if(find(x)==find(y))
printf("%lld\\n",v[find(x)]);
else
x=find(x),y=find(y);
if(search(x)!=search(y))
puts("-1");
else
make_root(x);
access(y);
splay(y);
printf("%lld\\n",sum[y]);
return 0;
以上是关于2959: 长跑|LCT+并查集的主要内容,如果未能解决你的问题,请参考以下文章