codeforces 877E - Danil and a Part-time Job

http://codeforces.com/contest/877/problem/E

题意:给你一棵树,每个结点 0 、 1 标记。有二种操作( 查询某个结点及其子结点 1 的个数、将某个结点及其子结点的标记取反)。

题解:线段树 

    w[i] 表示 i 结点在线段树上对应的编号, End[i] 表示 i 结点及其子结点在线段树上编号最大的结点编号

    这样 i 结点及其子结点就可以在线段树上用连续的编号 [ w[i], End[i] ] 表示。

  

int w[MAXN];
int End[MAXN], END = 0;
void dfs(int id, int pr)
{
    w[id] = ++END;
    for(int i = head[id]; ~i; i = edge[i].next)
    {
        int to = edge[i].to;
        if(to == pr) continue;
        dfs(to, id);
    }
    End[id] = END;
}

AC代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
using namespace std;
const int MAXN = 200000+10;
int n;
int a[MAXN];
struct node
{
    int to, next;
    node(){
    }
    node(int to, int next) : to(to), next(next){
    }
}edge[2*MAXN];
int head[MAXN], alledge;
void init()
{
    memset(head, 0xff, sizeof(head));
    alledge = 0;
}
void addedge(int x, int y)
{
    edge[alledge] = node(y, head[x]);
    head[x] = alledge++;
    edge[alledge] = node(x, head[y]);
    head[y] = alledge++;
}
int w[MAXN];
int End[MAXN], END = 0;
void dfs(int id, int pr)
{
    w[id] = ++END;
    for(int i = head[id]; ~i; i = edge[i].next)
    {
        int to = edge[i].to;
        if(to == pr) continue;
        dfs(to, id);
    }
    End[id] = END;
}
struct treenode
{
    int num;
    int flag;
}tree[MAXN<<2];
void build_tree(int id, int l, int r)
{
    if(l==r)
    {
        tree[id].num = a[l];
        tree[id].flag = 0;
        return ;
    }
    int mid = l+r>>1;
    build_tree(lson);
    build_tree(rson);
    tree[id].num = tree[id<<1].num+tree[id<<1|1].num;
}
void update(int id, int l, int r)
{
    tree[id].num = r-l+1-tree[id].num;
    tree[id].flag = !tree[id].flag;
}
void update(int id, int l, int r, int left, int right)
{
    if(l==left && r==right)
    {
        tree[id].num = r-l+1-tree[id].num;
        tree[id].flag = !tree[id].flag;
        return ;
    }
    int mid = l+r>>1;
    if( tree[id].flag )
    {
        update(lson);
        update(rson);
        tree[id].flag = 0;
    }
    if(right <= mid)
    {
        update(lson, left, right);
    }
    else if(left > mid)
    {
        update(rson, left, right);
    }
    else
    {
        update(lson, left, mid);
        update(rson, mid+1, right);
    }
    tree[id].num = tree[id<<1].num+tree[id<<1|1].num;
}
int query(int id, int l, int r, int left, int right)
{
    if(l==left && r==right)
    {
        return tree[id].num;
    }
    int mid = l+r>>1;
    if( tree[id].flag )
    {
        update(lson);
        update(rson);
        tree[id].flag = 0;
    }
    if(right <= mid)
    {
        return query(lson, left, right);
    }
    else if(left > mid)
    {
        return query(rson, left, right);
    }
    else
    {
        return query(lson, left, mid) + query(rson, mid+1, right);
    }
}
int main (void)
{
    ios::sync_with_stdio(false);
    init();
    cin >> n;
    for(int i = 2; i <= n; ++i)
    {
        int x; cin >> x;
        addedge(x, i);
    }
    dfs(1, -1);
    for(int i = 1; i <= n; ++i)
    {
        int x; cin >> x;
        a[w[i]] = x;
    }
    build_tree(1, 1, n);
    int q; cin >> q;
    while(q--)
    {
        string c; int x; cin >> c >> x;
        if( c == "pow") update(1, 1, n, w[x], End[x]);
        else cout<<query(1, 1, n, w[x], End[x])<<endl;
    }
    return 0;
}

 

posted @ 2017-10-24 21:55  黑.白  阅读(620)  评论(0编辑  收藏  举报