CodeForces 877E DFS序+线段树

时间:2019-08-24
本文章向大家介绍CodeForces 877E DFS序+线段树,主要包括CodeForces 877E DFS序+线段树使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

CodeForces 877E DFS序+线段树

题意

就是树上有n个点,然后每个点都有一盏灯,给出初始的状态,1表示亮,0表示不亮,然后有两种操作,第一种是get x,表示你需要输出x的子树和x本身一共有几个灯是亮的。pow x,表示你需要改变x的子树和x本身上的灯的状态。

题解思路

这个题肯定是用DFS序了,为啥?因为树不好操作啊(我也不会啊),使用DFS序可以把树压成一维的一串数,这样就可以使用线段树来进行区间操作了。

话说这个题是我暑假限时训练中做的,看到这个题老开心了,但是让我万万没想到的是,这个题我交了11次才过,太心酸了。

代码实现

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<vector>
using namespace std;
const int  maxn=2e5+100;
struct node{
    int l, r;
    int sum;
    int lazy;
}t[maxn<<2];
vector<int> g[maxn];
int num[maxn];
int in[maxn], out[maxn], rk[maxn], cnt;
int n, m;
void dfs(int u, int fa) //
{
    in[u]=++cnt;//这个是u进去的是时间
    rk[cnt]=u; //不要忘了这个,这个是新生成的序列,也就是树被压成一维的那个数列。就是这忘了,害的我好苦。
    int len=g[u].size();
    for(int i=0; i<len; i++)
    {
        int v=g[u][i];
        if(v==fa) continue;
        dfs(v, u);  
    }   
    out[u]=cnt;
}
void up(int rt)
{
    t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum;
}
void build(int rt, int l, int r)
{
    t[rt].l=l;
    t[rt].r=r;
    t[rt].sum=0;
    t[rt].lazy=0;
    if(l==r)
    {
        t[rt].sum=num[rk[l]]; //这里也不要能错了,很重要。
        return ;
    }
    int  mid=(l+r)>>1;
    build(rt<<1, l, mid);
    build(rt<<1|1, mid+1, r);
    up(rt);
}
void down(int rt)
{
    if(t[rt].lazy==0) return ;
    int ls=rt<<1, rs=rt<<1|1;
    t[ls].lazy=!t[ls].lazy;
    t[ls].sum=t[ls].r-t[ls].l+1-t[ls].sum;
    
    t[rs].lazy=!t[rs].lazy;
    t[rs].sum=t[rs].r-t[rs].l+1-t[rs].sum;
    
    t[rt].lazy=0;
}
void update(int rt, int l, int r)
{
    if(l <= t[rt].l && t[rt].r <= r )
    {
        t[rt].lazy = !t[rt].lazy;
        t[rt].sum=t[rt].r-t[rt].l+1-t[rt].sum;
        return ;
    }
    down(rt);
    int mid=(t[rt].l+t[rt].r)>>1;
    if(l<=mid) update(rt<<1, l, r);
    if(r>mid)  update(rt<<1|1, l, r);
    up(rt);
}
int query(int rt, int l, int r)
{
    if(l <= t[rt].l && t[rt].r <= r)
    {
        return t[rt].sum;
    }
    int ans=0;
    down(rt);
    int mid=(t[rt].l+t[rt].r)>>1;
    if(l<=mid) ans+=query(rt<<1, l, r);
    if(r>mid) ans+=query(rt<<1|1, l, r);
    return ans;
}
void init()
{
    cnt=0;
    for(int i=0; i<=n; i++)
    {
        g[i].clear();
    }
}
int main()
{
    scanf("%d", &n);
    {
        cnt=0;
        int x;
        string op;
        if(n==1)
        {
            scanf("%d", &x);
            scanf("%d" , &m);
            while(m--)
            {
                int tmp;
                cin>>op;
                scanf("%d", &tmp);
                if(op=="get") printf("%d\n", x);
                else x=!x;
            }
            return 0;
        }
        for(int i=2; i<=n; i++)
        {
            scanf("%d", &x);
            g[x].push_back(i);
            g[i].push_back(x);
        }
        dfs(1, 0);
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &num[i]);
        }
        build(1, 1, n);
        scanf("%d", &m);
        for(int i=1; i<=m; i++)
        {
            cin>>op;
            scanf("%d", &x);
            if(op=="get")
            {
                printf("%d\n", query(1, in[x], out[x]));
            }
            else
            {
                update(1, in[x], out[x]);
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/alking1001/p/11405929.html