bzoj 2959: 长跑
Posted encodetalker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2959: 长跑相关的知识,希望对你有一定的参考价值。
可以看作是这道题的加强版:https://www.luogu.org/problemnew/show/P2542
看到动态维护\(Tarjan\)缩点就考虑使用\(LCT\),使用一个并查集\(f\)表示点\(i\)所在的点双的“标志”点是哪一个,\(link\)时分类讨论一下即可
然后这题卡常,我们无法使用\(findroot\),于是考虑再用一个并查集表示两点之间的连通性即可
剩下的就和那个弱化版差不多了
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
int n,m,fa[150050],con[150050],f[150050],tag[150050],ch[150050][2];
int val[150050],sum[150050],w[150050];
int read()
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) if (ch=='-') f=-1;ch=getchar();
while ((ch>='0') && (ch<='9')) x=x*10+(ch-'0');ch=getchar();
return x*f;
int find(int x)
if (f[x]==x) return x;
f[x]=find(f[x]);
return f[x];
int findcon(int x)
if (con[x]==x) return x;
con[x]=findcon(con[x]);
return con[x];
bool isroot(int x)
int fx=find(fa[x]);
return ((ch[fx][0]!=x) && (ch[fx][1]!=x));
void pushup(int x) sum[x]=w[x]+sum[ch[x][0]]+sum[ch[x][1]];
void puttag(int x) swap(ch[x][0],ch[x][1]);tag[x]^=1;
void pushdown(int x)
if (tag[x])
if (ch[x][0]) puttag(ch[x][0]);
if (ch[x][1]) puttag(ch[x][1]);
tag[x]=0;
void update(int x)
//if (x==1) cout << "NOW " << ch[x][0] << " " << ch[x][1] << endl;
if (!isroot(x)) update(find(fa[x]));pushdown(x);
void rotate(int x)
int y=find(fa[x]),z=find(fa[y]),k=(ch[y][1]==x),w=ch[x][k^1];
if (!isroot(y)) ch[z][ch[z][1]==y]=x;
ch[x][k^1]=y;ch[y][k]=w;
if (w) fa[w]=y;fa[y]=x;fa[x]=z;
pushup(y);pushup(x);
void splay(int x)
update(x);
while (!isroot(x))
int y=find(fa[x]),z=find(fa[y]);
if (!isroot(y))
if ((ch[z][1]==y)^(ch[y][1]==x)) rotate(x);else rotate(y);
rotate(x);
pushup(x);
void access(int x)
int y=0;
while (x)
splay(x);ch[x][1]=y;pushup(x);
y=x;fa[y]=find(fa[y]);x=find(fa[x]);
int findroot(int x)
access(x);splay(x);
while (ch[x][0])
pushdown(x);x=ch[x][0];
splay(x);return x;
void out()
cout <<endl;
rep(i,1,n) cout << ch[i][0] << " " << ch[i][1] <<" ";cout << endl;
cout << endl;
void makeroot(int x) access(x);splay(x);puttag(x);
void link(int x,int y) makeroot(x);fa[x]=y;
void split(int x,int y) makeroot(x);access(y);splay(y);
void cut(int x,int y) split(x,y);ch[y][0]=0;fa[x]=0;pushup(y);
void del(int x,int y)
f[x]=y;pushdown(x);
if (ch[x][0]) del(ch[x][0],y);
if (ch[x][1]) del(ch[x][1],y);
int main()
n=read();m=read();
rep(i,1,n)
val[i]=read();sum[i]=val[i];w[i]=val[i];
f[i]=i;con[i]=i;
rep(i,1,m)
int op=read(),x=read(),y=read();
if (op==1)
int fx=find(x),fy=find(y);
if (fx==fy) continue;
int cx=findcon(fx),cy=findcon(fy);
if (cx!=cy)
link(fx,fy);
con[cx]=cy;
else
split(fx,fy);w[fy]=sum[fy];
del(fy,fy);ch[fy][0]=0;pushup(fy);
else if (op==2)
int fx=find(x);splay(fx);
w[fx]+=(y-val[x]);sum[fx]+=(y-val[x]);
val[x]=y;pushup(fx);
else if (op==3)
int fx=find(x),fy=find(y);
int cx=findcon(fx),cy=findcon(fy);
if (cx!=cy) puts("-1");
else
split(fx,fy);
printf("%d\n",sum[fy]);
return 0;
/*
9 31
10 20 30 40 50 60 70 80 90
3 1 2
1 1 3
1 1 2
1 8 9
1 2 4
1 2 5
1 4 6
1 4 7
3 1 8
3 8 8
1 8 9
3 8 8
3 7 5
3 7 3
1 4 1
3 7 5
3 7 3
1 5 7
3 6 5
3 3 6
1 2 4
1 5 5
3 3 6
2 8 180
3 8 8
2 9 190
3 9 9
2 5 150
3 3 6
2 1 210
3 3 6
*/
以上是关于bzoj 2959: 长跑的主要内容,如果未能解决你的问题,请参考以下文章