2959: 长跑 LCT+dfs
2016-04-20 21:15
435 查看
不错的一道题目,可惜tsinsen被卡常了,在BZOJ A掉了。
由于我们可以多次经过一个点,那么如果形成了一个简单环,那么环内的每个点都可以被经过,所以可以把这样的环缩成一个点,权值就是原来所有点的权值之和。
这样每次连边的时候如果发现有环就缩点,用并查集维护。
然后就是裸的LCT。
由于我们可以多次经过一个点,那么如果形成了一个简单环,那么环内的每个点都可以被经过,所以可以把这样的环缩成一个点,权值就是原来所有点的权值之和。
这样每次连边的时候如果发现有环就缩点,用并查集维护。
然后就是裸的LCT。
#include<iostream> #include<cstdio> using namespace std; const int N=150005; int fa ,f ,g ,q ,tree [2],sum ,val ,a ,rev ; int n,m; inline int read() { int a=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();} return a*f; } int find1(int x) { return f[x]==x?x:f[x]=find1(f[x]); } int find2(int x) { return g[x]==x?x:g[x]=find2(g[x]); } inline bool isroot(int x) { return tree[find2(fa[x])][0]!=x&&tree[find2(fa[x])][1]!=x; } inline void pushup(int x) { sum[x]=sum[tree[x][0]]+sum[tree[x][1]]+val[x]; } inline void pushdown(int x) { if (rev[x]) { rev[x]^=1; rev[tree[x][0]]^=1; rev[tree[x][1]]^=1; swap(tree[x][0],tree[x][1]); } } inline void rotate(int x) { int y=find2(fa[x]),z=find2(fa[y]),l=tree[y][1]==x,r=l^1; if (!isroot(y)) tree[z][tree[z][1]==y]=x; fa[x]=z; fa[y]=x; fa[tree[x][r]]=y; tree[y][l]=tree[x][r]; tree[x][r]=y; pushup(y); } inline void splay(int x) { int top=0; q[++top]=x; for (int i=x;!isroot(i);i=find2(fa[i])) q[++top]=find2(fa[i]); while (top) pushdown(q[top--]); while (!isroot(x)) { int y=find2(fa[x]),z=find2(fa[y]); if (!isroot(y)) { if (tree[y][0]==x^tree[z][0]==y) rotate(x); else rotate(y); } rotate(x); } pushup(x); } inline void access(int x) { for (int t=0;x;t=x,x=find2(fa[x])) splay(x),tree[x][1]=t,pushup(x); } inline void makeroot(int x) { access(x); splay(x); rev[x]^=1; } inline void link(int x,int y) { makeroot(x); fa[x]=y; } void dfs(int x,int F) { if (!x) return; pushdown(x); g[x]=F; if (x!=F) val[F]+=val[x]; dfs(tree[x][0],F); dfs(tree[x][1],F); tree[x][0]=tree[x][1]=0; } int main() { n=read(); m=read(); for (int i=1;i<=n;i++) a[i]=val[i]=read(); for (int i=1;i<=n;i++) f[i]=g[i]=i; for (int i=1;i<=m;i++) { int opt=read(),x=read(),y=read(); if (opt==1) { int p=find2(x),q=find2(y); if (p==q) continue; int P=find1(x),Q=find1(y); if (P!=Q) f[P]=Q,link(p,q); else makeroot(p),access(q),splay(q),dfs(q,q),pushup(q); } else if (opt==2) { int now=find2(x); splay(now); val[now]+=y-a[x]; a[x]=y; pushup(now); } else { int p=find2(x),q=find2(y); int P=find1(x),Q=find1(y); if (P!=Q) puts("-1"); else makeroot(p),access(q),splay(q),printf("%d\n",sum[q]); } } return 0; }
相关文章推荐
- lnmp安装脚本
- POJ-2406 Power Strings
- UVA-1630 Folding (KMP、区间dp)
- 【解题报告】BestCoder Round #80
- linux根目录下各个子目录的作用(精简版)
- 线程同步
- Java字符串格式化记录
- 阿里笔试第三题
- 整数类型_进制转换
- C++ 遇到的bug,自己的问题,交叉引用了
- c++ 如何获取系统时间
- 阿里笔试第二题
- win7 Microsoft IIS的配置(1)
- 代码统计工具java 实现
- PostgreSQL 与 PostGIS 在CentOS上的安装
- Opencv drawContours函数用于绘制和填充
- nginx root&alias文件路径配置
- 归并树(POJ 2104 K-th Number)
- 阿里笔试第一题
- 善之牧者