CF877E Danil and a Part-time Job 线段树维护dfs序

Posted olinr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF877E Danil and a Part-time Job 线段树维护dfs序相关的知识,希望对你有一定的参考价值。

(color{#0066ff}{题目描述})

有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0
共有 m 次操作,操作分为两种

get 询问一个点 x 的子树里有多少个 1
pow 将一个点 x 的子树中所有节点取反

对于每个 get 给出答案

(color{#0066ff}{输入格式})

第一行一个整数 n
第二行共 n?1 个整数,第 i 个数 (x_i) 表示 (x_i) 是 i+1 的父亲,
第三行给出每个点的初始权值
第四行一个整数 m
接下来 m 行为操作类型和位置

(color{#0066ff}{输出格式})

对于每个 get 给出答案

(color{#0066ff}{输入样例})

4
1 1 1
1 0 0 1
9
get 1
get 2
get 3
get 4
pow 1
get 1
get 2
get 3
get 4

(color{#0066ff}{输出样例})

2
0
0
1
2
1
1
0

(color{#0066ff}{数据范围与提示})

(1leq n leq 200000,1leq qleq 200000)

(color{#0066ff}{题解})

线段树维护dfs序

同一子树内dfs序连续

线段树上修改查询即可

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define _ 0
#define LL long long
#ifndef olinr
inline char getc()
{
    static char buf[100001],*p1=buf,*p2=buf;
    return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100001,stdin),p1==p2)? EOF:*p1++;
}
#else
#define getc() getchar()
#endif
inline LL in()
{
    LL x=0,f=1; char ch;
    while(!isdigit(ch=getc()))(ch=='-')&&(f=-f);
    while(isdigit(ch)) x=x*10+(ch^48),ch=getc();
    return x*f;
}
const int max=205005;
int val[max],dfn[max],redfn[max],siz[max];
class SGT
{
    private:
        struct node
        {
            int l,r;
            int val;
            node* ch[2];
            bool tag;
            node(int l,int r,int val,int tag):l(l),r(r),val(val),tag(tag){}
            void upd() {val=ch[0]->val+ch[1]->val;}
            int mid() {return (l+r)>>1;}
            int siz() {return r-l+1;}
            void dwn()
            {
                if(!tag) return;
                ch[0]->val=ch[0]->siz()-ch[0]->val;
                ch[1]->val=ch[1]->siz()-ch[1]->val;
                ch[0]->tag^=1;
                ch[1]->tag^=1;
                tag=0;
            }
        };
        typedef node* nod;
    public:
        nod root;
        void build(nod &o,int l,int r)
        {
            o=new node(l,r,0,0);
            if(l==r) return (void)(o->val=val[redfn[l]]);
            build(o->ch[0],l,o->mid());
            build(o->ch[1],o->mid()+1,r);
            o->upd();
        }
        void lazy(nod o,int l,int r)
        {
            if(o->r<l||o->l>r) return;
            if(l<=o->l&&o->r<=r) 
            {
                o->tag^=1;
                o->val=o->siz()-o->val;
                return;
            } 
            o->dwn();
            lazy(o->ch[0],l,r),lazy(o->ch[1],l,r);
            o->upd();
        }
        int query(nod o,int l,int r)
        {
            if(o->r<l||o->l>r) return 0;
            if(l<=o->l&&o->r<=r) return o->val;
            o->dwn();
            return query(o->ch[0],l,r)+query(o->ch[1],l,r);
        }
}s;
struct node
{
    int to;
    node *nxt;
    node(int to,node *nxt):to(to),nxt(nxt){}
};
typedef node* nod;
nod head[max];
int cnt;
void add(int from,int to)
{
    nod t=new node(to,head[from]);
    head[from]=t;
}
void dfs(int x,int f)
{
    siz[x]=1;
    dfn[x]=++cnt;
    redfn[cnt]=x;
    for(nod i=head[x];i;i=i->nxt)
        if(i->to!=f) dfs(i->to,x),siz[x]+=siz[i->to];
}
int n,m;

int main()
{   
    n=in(); int x;
    for(int i=1;i<=n-1;i++) x=in(),add(x,i+1),add(i+1,x);
    for(int i=1;i<=n;i++) val[i]=in();
    dfs(1,0);
    s.build(s.root,1,n);
    m=in();
    char ch;
    while(m--)
    {
        while(!isalpha(ch=getc()));
        x=in();
        if(ch=='g') printf("%d
",s.query(s.root,dfn[x],dfn[x]+siz[x]-1));
        else s.lazy(s.root,dfn[x],dfn[x]+siz[x]-1);
    }
    return 0;
}

以上是关于CF877E Danil and a Part-time Job 线段树维护dfs序的主要内容,如果未能解决你的问题,请参考以下文章

877E - Danil and a Part-time Job(dfs序+线段树)

codefroces 877E - Danil and a Part-time Job

Codeforces 877E - Danil and a Part-time Job 线段树+dfs序

Codeforces Round #442 (Div. 2) 877E - Danil and a Part-time Job dfs序+线段树

Vika and Segments - CF610D

cf--703--A-- Mishka and Game