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;
}
原文地址:https://www.cnblogs.com/olinr/p/10081036.html