zoukankan      html  css  js  c++  java
  • 洛谷SP16580 QTREE7

    洛谷题目传送门

    思路分析

    维护子树最值还是第一次写QwQ
    因为子树的最值会变化,所以不能简单地把最值记下来,还要维护一个平衡树,把每个子树的最大值扔进去,来资磁插入、删除和查询最值。
    然后我就懒得手写了,毕竟Splay作为平衡树时与LCT中的Splay写法不一样,不能混用。
    于是要去学习STL啦
    非常感谢Kelin巨佬的代码,我终于初步掌握了一下set的用法
    (比如说知道了multiset的erase某值是把所有等于该值的节点删除。。。。。。)
    (还比如说知道了rbegin和end的区别。。。。。。)
    于是就OK了,因为维护同色连通块的方法和Qtree6是一样的,建议先做Qtree6
    顺便放一下蒟蒻的Qtree6题解
    这题细节貌似有点多,放注释里

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<set>
    using namespace std;
    #define R register int
    #define I inline void
    const int N=100009,M=N<<1;
    #define lc c[x][0]
    #define rc c[x][1]
    #define C lct[col[x]]
    #define G ch=getchar()
    template<typename T>
    I gi(register T&z){
    	register char G;register bool fl=0;
    	while(ch<'-')G;
    	if(ch=='-')fl=1,G;
    	z=ch&15;G;
    	while(ch>'-')z*=10,z+=ch&15,G;
    	if(fl)z=-z;
    }
    int fa[N],v[N],he[N],ne[M],to[M];
    bool col[N];
    struct LCT{
    	int f[N],c[N][2],mx[N];
    	bool r[N];
    	multiset<int>s[N];
    	LCT(){mx[0]=-2147483647;}//因为点权可能为负,所以空节点要设成-inf
    	inline bool nroot(R x){return c[f[x]][0]==x||c[f[x]][1]==x;}
    	I pushup(R x){
    		mx[x]=max(v[x],max(mx[lc],mx[rc]));
    		if(!s[x].empty())mx[x]=max(mx[x],*s[x].rbegin());
    	}
    	I rotate(R x){
    		R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
    		if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;
    		f[w]=y;f[y]=x;f[x]=z;
    		pushup(y);
    	}
    	I splay(R x){
    		R y;
    		while(nroot(x)){
    			if(nroot(y=f[x]))rotate((c[f[y]][0]==y)^(c[y][0]==x)?x:y);
    			rotate(x);
    		}
    		pushup(x);
    	}
    	I access(R x){
    		for(R y=0;x;x=f[y=x]){
    			splay(x);
    			if(rc)s[x].insert(mx[rc]);
    			if((rc=y))s[x].erase(s[x].find(mx[y]));
    			pushup(x);
    		}//跟维护信息和有点像,也是加一个减一个
    	}
    	inline int findroot(R x){
    		access(x);splay(x);
    		while(lc)x=lc;
    		splay(x);
    		return x;
    	}
    	I link(R x){
    		splay(x);
    		R y=f[x]=fa[x];
    		access(y);splay(y);
    		c[y][1]=x;pushup(y);
    	}//另一种link写法,也是看Kelin巨佬代码学的
    //这里连的是实边,因为连虚边更新信息还有点麻烦
    	I cut(R x){
    		access(x);splay(x);
    		lc=f[lc]=0;
    		pushup(x);
    	}
    	I update(R x){
    		access(x);splay(x);
    		gi(v[x]);pushup(x);
    	}
    }lct[2];
    void dfs(R x,R y){
    	fa[x]=y;
    	for(R i=he[x];i;i=ne[i])
    		if(to[i]!=y)dfs(to[i],x);
    	C.link(x);
    }
    int main(){
    	R p=1,n,m,i,x,y,op;
    	gi(n);
    	for(i=1;i<n;++i){
    		gi(x);gi(y);
    		to[++p]=y;ne[p]=he[x];he[x]=p;
    		to[++p]=x;ne[p]=he[y];he[y]=p;
    	}
    	for(i=1;i<=n;++i)gi(col[i]);
    	for(i=1;i<=n;++i)gi(v[i]);
    	dfs(1,fa[1]=n+1);
    	gi(m);
    	while(m--){
    		gi(op);gi(x);
    		switch(op){
    		case 0:printf("%d
    ",C.mx[C.c[C.findroot(x)][1]]);break;
    		case 1:C.cut(x);col[x]^=1;C.link(x);break;
    		case 2:C.update(x);//AC后和Kelin巨佬的代码对比,发现我只更新了一个LCT中的,居然对了?!跟我的写法有关吧。。。。。。因为每次findroot我都splay到了根,直接改是对的吧
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    碰撞器与触发器[Unity]
    Mesh属性[Unity]
    4.3之后的PingPong效果实现
    windows reload()
    浏览器的内核
    redis 1
    oauth 2.0转
    java 散列
    js 事件详解 冒泡
    HttpURLConnection和HttpClient的区别2(转)
  • 原文地址:https://www.cnblogs.com/flashhu/p/8640576.html
Copyright © 2011-2022 走看看