[Spoj16580]Qtree7

题意:询问与 u u 相同颜色的联通块的中的最大点权,带修改

这题是Qtree6稍微加强了一下,思想和 Qtree6 Q t r e e 6 一样,就是维护的信息不同

其实维护颜色相同的联通块基本上是这个套路稳了

这道题维护子树信息的话要开一个 set s e t 维护虚儿子的最大值

推荐先做完 Qtree6 Q t r e e 6 ,这里是 Qtree6 Q t r e e 6 的题解

具体实现和一些细节看代码

#include<bits/stdc++.h>
#define fp(i,a,b) for(int i=a,I=b;i<=I;++i)
#define go(i,u) for(int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void sd(T&x){
    char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45)y=-1;x=c^48;
    while(c=gc(),47<c&&c<58)x=(x<<1)+(x<<3)+(c^48);x*=y;
}
char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
template<class T>inline void we(T x){
    if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=1e5+5,inf=-1u>>1;
typedef int arr[N];
struct eg{int nx,to;}e[N<<1];
int n,m,ce;arr fi,fa,col;
struct LCT{
    int Col,ch[N][2];arr fa,w,val;multiset<int>tp[N];
    #define lc(u)(ch[u][0])
    #define rc(u)(ch[u][1])
    inline bool ir(int u){return lc(fa[u])^u&&rc(fa[u])^u;}
    inline bool gf(int u){return rc(fa[u])==u;}
    inline void up(int u){w[u]=max(max(tp[u].empty()?-inf:*tp[u].rbegin(),max(w[lc(u)],w[rc(u)])),val[u]);}
    inline void rot(int u){
        int p=fa[u],k=gf(u);
        if(!ir(p))ch[fa[p]][gf(p)]=u;
        if(ch[u][!k])fa[ch[u][!k]]=p;
        ch[p][k]=ch[u][!k],ch[u][!k]=p;
        fa[u]=fa[p],fa[p]=u,up(p);
    }
    void splay(int u){
        for(int f=fa[u];!ir(u);rot(u),f=fa[u])
            if(!ir(f))rot(gf(u)==gf(f)?f:u);
        up(u);
    }
    inline void acc(int u){
        for(int v=0;u;u=fa[v=u]){
            splay(u);
            if(ch[u][1])tp[u].insert(w[ch[u][1]]);
            if(v)tp[u].erase(tp[u].find(w[v]));
            ch[u][1]=v,up(u);
        }
    }
    inline void brt(int u){acc(u),splay(u);}
    inline void link(int u,int v){
        if(!v)return;
        brt(v),splay(u),ch[fa[u]=v][1]=u,up(v);
    }
    inline void cut(int u,int v){
        if(!v)return;
        brt(u),fa[lc(u)]=0,lc(u)=0,up(u);
    }
    inline int Gf(int u){brt(u);while(lc(u))u=lc(u);return u;}
    inline int qry(int u){
        int p=Gf(u);splay(p);
        return col[p]==Col?w[p]:w[ch[p][1]];
    }
    inline void mdy(int u,int x){brt(u),val[u]=x,up(u);}
}T[2];
inline void add(int u,int v){e[++ce]=eg{fi[u],v},fi[u]=ce;}
void dfs(int u){go(i,u)if(v!=fa[u])T[col[v]].link(v,u),fa[v]=u,dfs(v);}
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    sd(n),T[1].Col=1;int u,v;
    fp(i,2,n)sd(u),sd(v),add(u,v),add(v,u);
    fp(i,1,n)sd(col[i]);fp(i,1,n)sd(T[0].val[i]),T[1].val[i]=T[0].val[i];
    fp(c,0,1)fp(i,1,n)T[c].w[i]=T[c].val[i];dfs(1);sd(m);
    while(m--){
        sd(v),sd(u);int&c=col[u];
        if(!v) we(T[c].qry(u));
        else if(v==1)T[c].cut(u,fa[u]),c^=1,T[c].link(u,fa[u]); 
        else sd(v),T[0].mdy(u,v),T[1].mdy(u,v);
    }
return Ot(),0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值