您的位置:首页 > 其它

codeforces 877 problem E Danil and a Part-time Job 【dfs序 + 线段树区间异或修改】

2017-11-06 15:11 465 查看
传送门

//题意: 给定一颗有根(1 )树,树上每一个点起始都有一个值(0或1),然后有两个操作,pow x把以 x为根的子树全部异或1, get x输出以x为根的子树中有多少个1.

//思路: 就是一个最裸的dfs序 + 线段树异或修改的,细节请看代码. 注意就是求一个区间中的1,那么就是区间长度-此时区间的值, 然后就是修改下lazy标记处就是了. 还有就是线段树中是dfs序的一些线段,所以在build过程中我们还需要知道此时的线段在树中对应的哪一个点,这样才能初始化.

AC Code

const int maxn = 2e5+5;
int cas=1;
int a[maxn];
int cnt,head[maxn];
int p1[maxn],p2[maxn];
int pre[maxn];
struct node
{
int to,next;
}e[maxn<<1];
void add(int u,int v)
{
e[cnt] = (node){v,head[u]};
head[u] = cnt++;
}
int ti;
void dfs_id(int u,int fa)
{
p1[u] = ++ti;
pre[ti] = u;
for(int i=head[u]; ~i ; i = e[i].next){
int to = e[i].to;
if(fa == to) continue;
dfs_id(to,u);
}
p2[u] = ti;
} //p1存的是第一次遇到时序号,p2是第二次遇到的序号.
//那么结点u及其子树存在的连续区间就是p1[u] - p2[u].
struct Tree{
int tl, tr, sum ,lazy;
void fun(int tot) {
lazy ^= 1;
sum = tot - sum;
}
} tree[maxn<<2];

void pushup(int id)
{
tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
}

void pushdown(int id,int l,int r)
{
if(tree[id].lazy){
int mid = (l+r)>>1;
tree[id<<1].fun(mid-l+1);
tree[id<<1|1].fun(r-mid);
tree[id].lazy = 0;
}
}

void build(int id,int l,int r)
{
tree[id].tl = l; tree[id].tr = r; tree[id].lazy = 0;
if(l == r){
tree[id].sum = a[pre[l]];
return ;
}
int mid = (l+r) >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}

void update(int id,int st,int ed)
{
int l=tree[id].tl, r=tree[id].tr;
if(st <= l && r <= ed){
tree[id].fun(r-l+1);
return ;
}
pushdown(id,l,r);
int mid = (l+r) >> 1;
if(st <= mid) update(id<<1,st,ed);
if(ed > mid) update(id<<1|1,st,ed);
pushup(id);
}
int ans;
void query(int id,int ql,int qr)
{
int l = tree[id].tl , r = tree[id].tr;
if(ql <= l && r <= qr) {
ans += tree[id].sum;
return ;
}
pushdown(id,l,r);
int mid = (l+r) >> 1;
if(ql <= mid) query(id<<1,ql,qr);
if(qr > mid) query(id<<1|1,ql,qr);
}

void solve()
{
int n; scanf("%d",&n);
ti = 0; Fill(pre,0);
cnt = 0; Fill(head,-1);
for(int i=2;i<=n;i++){
int u;
scanf("%d",&u);
add(i,u); add(u,i);
}
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
}
dfs_id(1,-1);
build(1,1,n);
int q; scanf("%d",&q);
while(q--){
string s; cin >> s;
int u; scanf("%d",&u);
if(s == "get"){
ans = 0;
query(1,p1[u],p2[u]);
printf("%d\n",ans);
}
else{
update(1,p1[u],p2[u]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐