zoukankan      html  css  js  c++  java
  • [BZOJ2959]长跑

    BZOJ

    sol

    维护点的连通关系和双连通关系,双连通分量就可以缩成一个点,开一个并查集搞一搞。
    所以注意每一次跳父亲都要找他在并查集里面的根,即所有的fa[x]都要写成find(fa[x])
    像这种没有cut的LCT题目最好写并查集维护连通性,常数!

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N = 150005;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    int n,m,fa[N],ch[2][N],rev[N],w[N],val[N],sum[N],con[N],scc[N],Stack[N],top;
    int find(int x){return x==scc[x]?x:scc[x]=find(scc[x]);}
    int Find(int x){return x==con[x]?x:con[x]=Find(con[x]);}
    bool son(int x){return ch[1][find(fa[x])]==x;}
    bool isroot(int x){return ch[0][find(fa[x])]!=x&&ch[1][find(fa[x])]!=x;}
    void reverse(int x){if(!x)return;swap(ch[0][x],ch[1][x]);rev[x]^=1;}
    void pushup(int x){sum[x]=sum[ch[0][x]]+sum[ch[1][x]]+val[x];}
    void pushdown(int x){if(!rev[x])return;reverse(ch[0][x]);reverse(ch[1][x]);rev[x]=0;}
    void rotate(int x)
    {
    	int y=find(fa[x]),z=find(fa[y]),c=son(x);
    	ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
    	fa[x]=z;if (!isroot(y)) ch[son(y)][z]=x;
    	ch[c^1][x]=y;fa[y]=x;pushup(y);
    }
    void splay(int x)
    {
    	Stack[top=1]=x;
    	for (int y=x;!isroot(y);y=find(fa[y])) Stack[++top]=find(fa[y]);
    	while (top) pushdown(Stack[top--]);
    	for (int y=find(fa[x]);!isroot(x);rotate(x),y=find(fa[x]))
    		if (!isroot(y)) son(x)^son(y)?rotate(x):rotate(y);
    	pushup(x);
    }
    void access(int x){for (int y=0;x;y=x,x=find(fa[x])) splay(x),ch[1][x]=y,pushup(x);}
    void makeroot(int x){access(x);splay(x);reverse(x);}
    void split(int x,int y){makeroot(x);access(y);splay(y);}
    void link(int x,int y){makeroot(x);fa[x]=y;}
    void dfs(int x,int rt){if(!x)return;scc[find(x)]=rt;dfs(ch[0][x],rt);dfs(ch[1][x],rt);}
    int main()
    {
    	n=gi();m=gi();
    	for (int i=1;i<=n;++i) con[i]=scc[i]=i,w[i]=val[i]=gi();
    	while (m--)
    	{
    		int opt=gi(),u=gi(),v=gi();
    		if (opt==1)
    		{
    			u=find(u);v=find(v);
    			if (Find(u)!=Find(v)) link(u,v),con[Find(u)]=Find(v);
    			else{
    				split(u,v);val[v]=sum[v];
    				dfs(v,v);ch[0][v]=ch[1][v]=0;
    			}
    		}
    		if (opt==2)
    		{
    			int fu=find(u);
    			splay(fu);val[fu]+=v-w[u];w[u]=v;pushup(fu);
    		}
    		if (opt==3)
    		{
    			u=find(u);v=find(v);
    			if (Find(u)^Find(v)) {puts("-1");continue;}
    			split(u,v);printf("%d
    ",sum[v]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    C#基础—string等类的有趣方法_1
    设计模式
    OOP-面向对象程序设计
    CSS3实用效果大全
    HTML5 DOM元素类名相关操作API classList简介(转载自张鑫旭大神)
    Js写的一个倒计时效果实例
    垂直居中的几种方案
    大图片加载优化解决方案
    DomReady实现策略
    脱离文档流
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8424129.html
Copyright © 2011-2022 走看看