Codeforces Round #200 (Div. 1)D Water Tree

传送门

题意

给你 n ( n < = 5 e 5 ) n(n<=5e5) 个节点的树。 m ( m < = 5 e 5 ) m(m<=5e5) 个操作

  • 1 v 把v和儿子全部置为1
  • 2 v 把root到v之间全部置为0
  • 3 v 查询v

思路

树上的区间操作,很明显的一个树链刨分+线段树维护
线段树的flag数组表示置为0或者1.
区间修改+单点查询

代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 5e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
int id[man],rk[man],top[man],siz[man];
int son[man],dep[man],fa[man];
vector<int>sp[man];

void dfs1(int u,int f,int d){
    son[u] = 0;
    dep[u] = d;
    fa[u] = f;
    siz[u] = 1;
    for(int i = 0;i < sp[u].size();i++){
        int v = sp[u][i];
        if(v==f)continue;
        dfs1(v,u,d+1);
        siz[u] += siz[v];
        if(siz[son[u]]<siz[v]){
            son[u] = v;
        }
    }
}

int cnt = 0;
void dfs2(int u,int tp){
    id[u] = ++cnt;
    rk[cnt] = u;
    top[u] = tp;
    if(!son[u])return;
    dfs2(son[u],tp);
    for(int i = 0;i < sp[u].size();i++){
        int v = sp[u][i];
        if(v==son[u]||v==fa[u])continue;
        dfs2(v,v);
    }
}

int flag[man<<2],tr[man<<2],a[man];
void pushdown(int rt){
    if(flag[rt]){
        flag[rt<<1] = flag[rt];
        flag[rt<<1|1] = flag[rt];
        tr[rt<<1] = (flag[rt]==1 ? 1 : 0);
        tr[rt<<1|1] = (flag[rt]==1 ? 1 : 0);
        flag[rt] = 0;
    }
}

void update(int l,int r,int L,int R,int rt,int op){
    if(L<=l&&r<=R){
        flag[rt] = op;//1 full  2 empty
        tr[rt] = (op==1 ? 1 : 0);
        return;
    }
    int m = l + r >> 1;
    pushdown(rt);
    if(L<=m)update(l,m,L,R,rt<<1,op);
    if(R>m)update(m+1,r,L,R,rt<<1|1,op);
}


int query(int l,int r,int rt,int v){
    if(l==r){
        return tr[rt];
    }
    int m = l + r >> 1;
    pushdown(rt);
    if(v<=m)return query(l,m,rt<<1,v);
    else return query(m+1,r,rt<<1|1,v);
}

void tree_update(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]]){
            swap(x,y);
        }
        update(1,cnt,id[top[x]],id[x],1,2);
        x = fa[top[x]];
        //cout << x << " "<< top[x] << " "<< y  << endl;
    }
    if(dep[x]<dep[y]){
        swap(x,y);
    }
    
    update(1,cnt,id[y],id[x],1,2);
    //cout << x << " "<< y  << endl;
}


int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt","w",stdout);
    #endif
    int n;
    scanf("%d",&n);
    for(int i = 1;i < n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        sp[u].push_back(v);
        sp[v].push_back(u);
    }
    int m;
    dfs1(1,1,1);
    dfs2(1,1);
    // for(int i = 1;i <= n;i++){
    //     cout << id[i] << " " <<rk[id[i]] << endl;
    // }
    scanf("%d",&m);
    for(int i = 1;i <= m;i++){
        int op;
        scanf("%d",&op);
        //cout << "op" << op << endl;
        if(1==op){
            int v;scanf("%d",&v);
            update(1,cnt,id[v],id[v]+siz[v]-1,1,1);
        }else if(2==op){
            int v;scanf("%d",&v);
            tree_update(1,v);
        }else{
            int v;scanf("%d",&v);
           // cout << "v:" << v << endl;
            printf("%d\n",query(1,cnt,1,id[v]));
        }
    }
    return 0;
}
发布了27 篇原创文章 · 获赞 7 · 访问量 2691

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/103510057