QTREE6&&7 - Query on a tree VI &&VII

树上连通块

不用具体距离,只询问连通块大小或者最大权值

可以类比Qtree5的方法,但是记录东西很多,例如子树有无0/1颜色等

一个trick,两个LCT分离颜色

每个颜色在边上。

仅保留连通块顶部不是相同颜色,使得断边不会被菊花图卡掉

所以内部颜色不用考虑了,专心维护子树值。

查询时候findrt,splay,右儿子即可。

 

Qtree6

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}

namespace Miracle{
const int N=1000000+5;
int n,m;
int f[N];
int co[N];
struct LCT{
    #define ls ch[x][0]
    #define rs ch[x][1]
    int fa[N],ch[N][2];
    int sz[N],si[N];
    bool nrt(int x){
        return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
    }
    void pushup(int x){
        if(x)
        sz[x]=si[x]+sz[ls]+sz[rs]+1;
    }
    void rotate(int x){
        int y=fa[x],d=ch[y][1]==x;
        fa[ch[y][d]=ch[x][!d]]=y;
        if(nrt(y)) ch[fa[x]=fa[y]][ch[fa[y]][1]==y]=x;
        else fa[x]=fa[y];
        fa[ch[x][!d]=y]=x;
        pushup(y);
    }
    void splay(int x){
        while(nrt(x)){
            int y=fa[x],z=fa[y];
            if(nrt(y)){
                rotate((ch[y][0]==x)==(ch[z][0]==y)?y:x);
            }
            rotate(x);
        }
        pushup(x);
    }
    void access(int x){
        for(reg y=0;x;y=x,x=fa[x]){
            //cout<<" xx "<<x<<endl;
            splay(x);si[x]-=sz[y];si[x]+=sz[ch[x][1]];
            ch[x][1]=y;
            pushup(x);
        }
    }
    int findrt(int x){
        access(x);splay(x);
        while(ch[x][0]) x=ch[x][0];
        splay(x);
        return x;
    }
    void link(int x){
        //cout<<" link "<<x<<endl;
        splay(x);
        int y=fa[x]=f[x];
        access(y);splay(y);
        si[y]+=sz[x];
        pushup(y);
    }
    void cut(int x){
    //    cout<<" cut "<<x<<endl;
        access(x);splay(x);
    //    cout<<ls<<" "<<ch[x][0]<<endl;
        ls=fa[ls]=0;
        pushup(x);
    }
    int query(int x){
        int lp=findrt(x);
    //    cout<<" lp "<<lp<<" "<<sz[lp]<<" "<<si[lp]<<endl;
        return sz[lp]-si[lp]-1;
    }
}lct[2];
vector<int>to[N];
void dfs(int x){
    for(reg i=0;i<(int)to[x].size();++i){
        if(to[x][i]!=f[x]){
            f[to[x][i]]=x;dfs(to[x][i]);
            lct[1].link(to[x][i]);
        }
    }
}
int main(){
    rd(n);
    int x,y;
    for(reg i=1;i<n;++i)rd(x),rd(y),to[x].push_back(y),to[y].push_back(x);
    for(reg i=1;i<=n+1;++i) lct[0].sz[i]=1,lct[1].sz[i]=1,co[i]=1;
    to[n+1].push_back(1);
    dfs(n+1);
    int op;
    rd(m);
    while(m--){
        rd(op);rd(x);
        if(!op){
            printf("%d\n",lct[co[x]].query(x));
        }else{
            lct[co[x]].cut(x);
        //    cout<<" after co[x] cut "<<endl;
            lct[co[x]^1].link(x);
            co[x]^=1;
        }
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/3/15 10:57:40
*/
View Code

Qtree7

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}

namespace Miracle{
const int N=1e5+5;
const int inf=0x3f3f3f3f;
int n,m;
int fa[N];
struct LCT{
    struct node{
        int ch[2],fa;
        int val;
        int ans;
        priority_queue<int>q,d;
        void dele(int c){
            d.push(c);
        }
        void ins(int c){
            q.push(c);
        }
        int top(){
            while(!q.empty()&&!d.empty()&&q.top()==d.top()) q.pop(),d.pop();
            if(!q.empty()) return q.top();
            return -inf;
        }
    }t[N];
    bool nrt(int x){
        return t[t[x].fa].ch[0]==x||t[t[x].fa].ch[1]==x;
    }
    void pushup(int x){
        t[x].ans=max(t[x].val,max(t[x].top(),max(t[t[x].ch[0]].ans,t[t[x].ch[1]].ans)));
    }
    void rotate(int x){
        int y=t[x].fa,d=t[y].ch[1]==x;
        t[t[y].ch[d]=t[x].ch[!d]].fa=y;
        if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
        else t[x].fa=t[y].fa;
        t[t[x].ch[!d]=y].fa=x;
        pushup(y);
    }
    void splay(int x){
        while(nrt(x)){
            int y=t[x].fa,z=t[y].fa;
            if(nrt(y)){
                rotate((t[y].ch[1]==x)==(t[z].ch[1]==y)?y:x);
            }rotate(x);
        }
        pushup(x);
    }
    void access(int x){
        for(reg y=0;x;y=x,x=t[x].fa){
            splay(x);t[x].dele(t[y].ans);
            t[x].ins(t[t[x].ch[1]].ans);
            t[x].ch[1]=y;
            pushup(x);
        }
    }
    int findrt(int x){
        access(x);splay(x);
        while(t[x].ch[0]) x=t[x].ch[0];
        splay(x);
        return x;
    }
    void link(int x){
    //    cout<<" link "<<x<<" t.fa "<<t[x].fa<<" fa "<<fa[x]<<" ans "<<t[x].ans<<" val "<<t[x].val<<endl;
        splay(x);
        int y=t[x].fa=fa[x];
        access(y);splay(y);
        t[y].ins(t[x].ans);
        pushup(y);
    }
    void cut(int x){
        access(x);splay(x);
        t[x].ch[0]=t[t[x].ch[0]].fa=0;
        pushup(x);
    }
    void chan(int x,int c){//chan val
        access(x);splay(x);
        t[x].val=c;
        pushup(x);
    }
    int query(int x){
        int lp=findrt(x);
        return t[t[lp].ch[1]].ans;
    }
}lct[2];
vector<int>to[N];
int co[N],wei[N];
void dfs(int x){
    //cout<<x<<endl;
    for(reg i=0;i<(int)to[x].size();++i){
        int y=to[x][i];
        if(y==fa[x]) continue;
        fa[y]=x;
        dfs(y);
        lct[co[y]].link(y);
    }
}
int main(){

    rd(n);
    lct[0].t[0].ans=lct[0].t[0].val=-inf;
    lct[1].t[0].ans=lct[1].t[0].val=-inf;
    lct[0].t[n+1].ans=lct[0].t[n+1].val=-inf;
    lct[1].t[n+1].ans=lct[1].t[n+1].val=-inf;
    int x,y;
    for(reg i=1;i<n;++i){
        rd(x);rd(y);
        to[x].push_back(y);to[y].push_back(x);
    }
    to[n+1].push_back(1);
    for(reg i=1;i<=n;++i){
        rd(co[i]);
    }
    for(reg i=1;i<=n;++i){
        rd(wei[i]);
    //    cout<<" i "<<i<<" "<<wei[i]<<endl;
        lct[0].t[i].val=lct[0].t[i].ans=wei[i];
        lct[1].t[i].val=lct[1].t[i].ans=wei[i];
    }
    wei[n+1]=-inf;
    dfs(n+1);
    
    rd(m);int op;
    while(m--){
        rd(op);rd(x);
        if(op==0){
            printf("%d\n",lct[co[x]].query(x));
        }else if(op==1){
            lct[co[x]].cut(x);lct[co[x]^1].link(x);
            co[x]^=1;
        }else{
            rd(y);
            lct[0].chan(x,y);
            lct[1].chan(x,y);
        }
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/3/15 14:12:29
*/
View Code

 

posted @ 2019-03-15 14:56  *Miracle*  阅读(389)  评论(0编辑  收藏  举报