\(\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}{数据范围与提示}\)

\(1\leq n \leq 200000,1\leq q\leq 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\n",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序的更多相关文章

  1. CodeForces 343D 线段树维护dfs序

    给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u ...

  2. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

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

    题目链接:http://codeforces.com/contest/877/problem/E 题解:显然一看就感觉要么树链剖分要么线段树+dfs序,题目要求的操作显然用线段树+dfs序就可以实现. ...

  4. 【HIHOCODER 1576】 子树中的最小权值(线段树维护DFS序)

    描述 给定一棵N个节点的树,编号1~N.其中1号节点是根,并且第i个节点的权值是Vi. 针对这棵树,小Hi会询问小Ho一系列问题.每次小Hi会指定一个节点x,询问小Ho以x为根的子树中,最小的权值是多 ...

  5. bzoj 3779: 重组病毒【LCT+线段树维护dfs序】

    %.8lf会WA!!%.8lf会WA!!%.8lf会WA!!要%.10lf!! 和4817有点像,但是更复杂. 首先对于操作一"在编号为x的计算机中植入病毒的一个新变种,在植入一个新变种时, ...

  6. BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)

    题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...

  7. 2018.11.01 NOIP训练 图论(线段树+倍增+dfs序)

    传送门 一道挺妙的题. 对于询问点(u,v),如右图所示,我们可以发现存在一个点m在u->v的路径中,m子树的点到u是最近的,m子树外到v是最近的.其中dis(u,m)=(dis(u,v)-1) ...

  8. 线段树(dfs序建树加区间更新和单点查询)

    题目链接:https://cn.vjudge.net/contest/66989#problem/J 记录一下这道折磨了我一天的题,.... 具体思路: 具体关系可通过dfs序建树,但是注意,在更新以 ...

  9. CF620E New Year Tree 状压+线段树(+dfs序?)

    借用学长的活:60种颜色是突破口(我咋不知道QAQ) 好像这几道都是线段树+dfs序??于是你可以把60种颜色压进一个long long 里,然后向上合并的时候与一下(太妙了~) 所以记得开long ...

随机推荐

  1. postgresql 数据库,模式,表空间的关系

    数据库与模式模式(schema)是对数据库(database)逻辑分割在数据库创建的同时,就已经默认为数据库创建了一个模式--public,这也是该数据库的默认模式.所有为此数据库创建的对象(表.函数 ...

  2. 侯捷STL学习(六)--深入list && Iterator traits

    第十三,四节 深度探索list(上,下) list Gnu2.9源代码实现 注意node代码和图示的位置 实现前闭后开,增加一个空白节点 用的分配器alloc Iterator智能指针,需要知道结点n ...

  3. PhoneGap打Android包报错

    1.下载AndroidSDK,安装 2.下载Phonegap,解压,为以后打包用 3.下载Node.js,安装 4.下载并安装Ant工具 5.配置环境变量 ANT_HOME=ANT主目录路径 PATH ...

  4. Celery-4.1 用户指南: Routing Tasks (路由任务)

    注意: 像主题和扇出之类的路由概念并不对所有传输介质都可用,请翻阅”传输比较表”. 基础 自动路由 路由最简单的方式是使用 task_create_missing_queues 设置(默认启用). 使 ...

  5. GET与POST方法

    HTTP中的GET,POST,PUT,DELETE对应着对这个资源的查,改,增,删4个操作.GET一般用于获取/查询资源信息,而POST一般用于更新资源信息. 1.根据HTTP规范,GET用于信息获取 ...

  6. Android中无标题样式和全屏样式学习

    在进行UI设计时,我们经常需要将屏幕设置成无标题栏或者全屏.要实现起来也非常简单,主要有两种方法:配置xml文件和编写代码设置. 1.在xml文件中进行配置 在项目的清单文件AndroidManife ...

  7. Codeforces 960F 线段树

    题意:https://blog.csdn.net/qq_39809664/article/details/79871282 思路:我们考虑LIS的状态转移,对于这个题,假设现在扫描到的边是(u, v, ...

  8. 将字符串str1复制为字符串str2的三种方法

    1.自己编写函数,将两个字符串进行复制 #include<iostream> using namespace std; int main(){ char str1[]="I lo ...

  9. git在eclipse中的配置 完整版 转载

    http://www.cnblogs.com/zhxiaomiao/archive/2013/05/16/3081148.html

  10. C语言中的static的作用?

    在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)第一个作用:隐藏. 当我们同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性.为理解这句话 ...