P2146 [NOI2015] package manager (tree chain division + line segment tree interval coverage)

Topic link
Topic outline (simplified): Give you a tree, numbered from 0 to n-1, and give you two operations:

  1. in u Find how many 0s are on the path from node u to the root node, and set them to 1, output.
  2. un u Find how many 1s there are in the subtree rooted at u, output and set them to 0.

General idea: Obviously, searching for a subtree rooted at u can be directly modified in dfs order, but it is obviously impossible to find information violence on the path from u to the root node, so O(n) is obviously impossible, so consider the tree chain Split. Then the segment tree maintains interval information.
Note: In addition to the basic operation of the line segment tree, there is only one thing that needs attention, that is, the number starts from 0, if the node number does not increase by 1, the initial value of the son[] array must be set to -1, otherwise it will be infinite Jump, causing timeout. (The lesson of blood)

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#define lk (k<<1)
#define rk (k<<1|1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pi=acos(-1.0);
const double eps=1e-8;
const double INF=1e20;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
struct egde
{
    
    
    int v,next;
}e[N<<1];
int head[N],cnt;
void add(int u,int v)
{
    
    
    e[++cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt;
}
int top[N],dfn[N],len,out[N];
int fa[N],dep[N],son[N],size[N];
void dfs1(int u,int f)
{
    
    
    fa[u]=f;
    dep[u]=dep[f]+1;
    size[u]=1;
    son[u]=0;
    for(int i=head[u];i;i=e[i].next)
    {
    
    
        int v=e[i].v;
        if(v==f) continue;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[son[u]]) son[u]=v;
    }
}
void dfs2(int u)
{
    
    
    dfn[u]=++len;
    if(son[u])
    {
    
    
        top[son[u]]=top[u];
        dfs2(son[u]);
    }
    for(int i=head[u];i;i=e[i].next)
    {
    
    
        int v=e[i].v;
        if(!top[v])
        {
    
    
            top[v]=v;
            dfs2(v);
        }
    }
    out[u]=len;
}
struct node
{
    
    
    int l,r;
    int sum,lazy;
}t[N<<2];
inline void pushup(int k)
{
    
    
    t[k].sum=t[lk].sum+t[rk].sum;
}
inline void pushdown(int k)
{
    
    
    if(t[k].lazy!=-1)
    {
    
    
        t[lk].lazy=t[rk].lazy=t[k].lazy;
        t[lk].sum=(t[lk].r-t[lk].l+1)*t[k].lazy;
        t[rk].sum=(t[rk].r-t[rk].l+1)*t[k].lazy;
        t[k].lazy=-1;
    }
}
void build(int k,int l,int r)
{
    
    
    t[k].l=l;
    t[k].r=r;
    t[k].lazy=-1;
    t[k].sum=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(lk,l,mid);
    build(rk,mid+1,r);
}
int x;
void update(int k,int l,int r,int val)
{
    
    
    if(t[k].l>=l&&t[k].r<=r)
    {
    
    
        x+=t[k].sum;
        t[k].sum=(t[k].r-t[k].l+1)*val;
        t[k].lazy=val;
        return;
    }
    else
    {
    
    
        pushdown(k);
        int mid=(t[k].l+t[k].r)>>1;
        if(l<=mid) update(lk,l,r,val);
        if(r>mid) update(rk,l,r,val);
        pushup(k);
    }
}
int ask(int u,int v)
{
    
    
    int fu=top[u],fv=top[v];
    int ans=0;
    while(fu!=fv)
    {
    
    
        x=0;
        if(dep[fu]>=dep[fv])
        {
    
    
            update(1,dfn[fu],dfn[u],1);
            ans+=x;
            u=fa[fu];fu=top[u];
        }
        else {
    
    
            update(1,dfn[fv],dfn[v],1);
            ans+=x;
            v=fa[fv];fv=top[v];
        }
    }
    x=0;
    if(dep[u]>=dep[v]) update(1,dfn[v],dfn[u],1),ans+=x;
    else update(1,dfn[u],dfn[v],1),ans+=x;
    return ans;
}
int read()
{
    
    
    char c;
    int res=0,sign=1;
    c=getchar();
    while(c<'0'||c>'9')
    {
    
    
        if(c=='-') sign=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
    
    
        res=res*10+c-'0';
        c=getchar();
    }
    return sign*res;
}
void print(int x)
{
    
    
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int n,val,q,u,ans;
char s[10];
int main()
{
    
    
    cnt=len=0;
    n=read();
    for(int i=2;i<=n;i++)
    {
    
    
        val=read();
        val++;
        add(val,i);
        top[i]=0;
    }
    dfs1(1,0);
    top[1]=1;
    dfs2(1);
    build(1,1,len);
    q=read();
    while(q--)
    {
    
    
        scanf("%s",s);
        u=read();
        u++;
        x=0;
        if(s[0]=='i')
        {
    
    
            ans=ask(u,1);
            print(dep[u]-dep[1]+1-ans);
            putchar('\n');
        }
        else
        {
    
    
            update(1,dfn[u],out[u],0);
            print(x);
            putchar('\n');
        }
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/amazingee/article/details/109018121