[NOI2015] [package manager tree chain segment tree split interval coverage] +

Judge Online : Luogu-P2146

The Label : chain split tree, tree line interval coverage

Subject to the effect

\ (n-\) packages ( No. 1-n-~ 0 ), a dependency between them containing a \ (n-1 \) tree edges will be described. A total of two operations:

  • install x:表示安装软件包x
  • uninstall x:表示卸载软件包x

Installation \ (x \) , you must have to install x to all the packages on the root path ; and Uninstall \ (x \) , you must have to uninstall x subtree all installed packages . For each operation, the output of the operating front, the mounted state of the number of nodes generated changes .

To 100% of the data, \ (n-, Q <= 100000 \)

Entry

First line of the input file contains an integer n, denotes the total number of packages. Packages are numbered starting from zero.

Then line comprising n-1 integers, separated by a single space between adjacent integers, respectively numbered 1,2,3, ⋯, n-2, n-1 dependent packages No. package.

The next line contains an integer q, it represents the total number of inquiries. After the q rows of a query. Inquiry is divided into two types:

install x: x represents the installation package

uninstall x: x represents uninstall packages

You need to maintain the status of each package install, start all packages are not installed in the state.

For each operation, you need to output this operation will be the number of packages installed state change, subsequent application of this operation (ie you change the installation state of maintenance).

Export

Output file including q rows.

I-th row of the output file output an integer, the i-th step operation to change the number of packages mounted state.

Sample

Input#1

7
0 0 0 1 1 5
5
install 5
install 6
uninstall 1
install 4
uninstall 0

Output#1

3
1
3
2
3

answer

These two operations corresponding to the tree.

1. Install time:

The mounted state of all points on the path to the root node assignment x is installed: 1

2. unloaded:

The mounted state of point x in the subtree assigned not installed: 0

Found that two operations need to be a period of continuous intervals assignment , attention is not modified , but can use tree line is completed, the specific assignment and modification of the tree line interval difference specific in the end thebbset forth.

The first operation may use the tree split chain jump heavy chain, in O \ ((log 2N ^) \) is completed within a time hopping and the modified state of a point on the chain.

The second operation, directly from dfs sequence of subtrees corresponding to the section a section for assignment to, a single operation is the complexity of the \ (O (logN) \) .

The time complexity of the algorithm is the sum of \ (O (Q \ ^ CDOT log 2N) \) .

The complete code is as follows:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
inline int read(){
    int x=0;char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x;
}
struct edge{
    int to,nxt;
}e[N];
int head[N],cnt;
inline void link(int u,int v){e[++cnt]=(edge){v,head[u]};head[u]=cnt;}


struct node{
    int l,r,w,lazy;
}b[N<<2];
void build(int o,int l,int r){
    b[o].l=l,b[o].r=r,b[o].lazy=-1;
    if(l==r)return;
    int mid=l+r>>1;
    build(o<<1,l,mid),build(o<<1|1,mid+1,r);
}
void down(int o){
    int g=b[o].lazy;
    if(g==-1)return;
    b[o<<1].w=(b[o<<1].r-b[o<<1].l+1)*g;
    b[o<<1|1].w=(b[o<<1|1].r-b[o<<1|1].l+1)*g;
    b[o<<1].lazy=b[o<<1|1].lazy=g;
    b[o].lazy=-1;
}
void update(int o,int l,int r,int d){
    if(b[o].l==l&&b[o].r==r){
        b[o].w=(b[o].r-b[o].l+1)*d;
        b[o].lazy=d;
        return;
    }
    down(o);
    int mid=b[o].l+b[o].r>>1;
    if(r<=mid)update(o<<1,l,r,d);
    else if(l>=mid+1)update(o<<1|1,l,r,d);
    else{
        update(o<<1,l,mid,d);update(o<<1|1,mid+1,r,d);
    }
    b[o].w=b[o<<1].w+b[o<<1|1].w;
}


int n,q;
int sz[N],dep[N],fa[N],top[N],son[N];
int li[N],ri[N],tot;
void predfs(int x,int f){
    sz[x]=1;fa[x]=f;dep[x]=dep[f]+1;
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].to;
        predfs(y,x);
        sz[x]+=sz[y];
        if(!son[x]||sz[y]>sz[son[x]])son[x]=y;
    }
}
void redfs(int x,int tp){
    top[x]=tp;li[x]=++tot;
    if(son[x])redfs(son[x],tp);
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].to;
        if(y!=son[x])redfs(y,y);
    }
    ri[x]=tot;
}
void boom(int x,int y,int d){
    while(top[x]!=top[y]){      
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        update(1,li[top[x]],li[x],d);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    update(1,li[x],li[y],d);
}
int main(){
    n=read();
    for(int i=2,u;i<=n;i++){
        u=read();u++;
        link(u,i);
    }
    predfs(1,0);redfs(1,1);
    build(1,1,n);
    q=read();
    while(q--){
        char op[13];scanf("%s",op);
        int x=read(),base=b[1].w;
        x++;    
        if(op[0]=='i'){         
            boom(1,x,1);
            printf("%d\n",b[1].w-base);
        }
        else{   
            update(1,li[x],ri[x],0);
            printf("%d\n",base-b[1].w); 
        }
    }
}

End

By this question sort out a few common questions and templates:

A tree split chain

part1

Tree sectional Wujiantao: \ (SZ [], Son [], FA [], DEP [], Top [] \) (corresponding subtree size, weight son number, parent node ID, depth, those of the heavy chain the top node number)

Note that each point will fall on a heavy chain, when there is only one point, chain degenerate into a point, the only point is that section of the heavy chain top

part2

The realization of three main parts

predfs(root);//主要处理sz,son,fa,dep这四个数组
redfs(root,root);//主要处理top,题目需要时处理li[],ri[](dfs序)
calc(u,v);//统计路径(u,v)上的值、或者是对路径(u,v)进行修改

Here's a detail, processing dfs order when we have to in (redfs \) \ in progress, because we have to ensure a heavy chain on the \ (li [] \) is continuous , so as to be mapped to the tree line, to contiguous stretch of chain be modified interval. Of course, this treatment dfs sequence can still be represented by a node in the subtree -> \ ([Li [X], RI [X]] \) .

Template code is given below three portions

predfs

void predfs(int x,int f){
    sz[x]=1;fa[x]=f;dep[x]=dep[f]+1;
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].to;
        predfs(y,x);
        sz[x]+=sz[y];
        if(!son[x]||sz[y]>sz[son[x]])son[x]=y;
    }
}

redfs

void redfs(int x,int tp){
    top[x]=tp;li[x]=++tot;
    if(son[x])redfs(son[x],tp);
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].to;if(y!=son[x])redfs(y,y);
    }
    ri[x]=tot;
}

calc

Different topics, major changes in the third part, here are a few common problems the board

1. seeking LCA

int LCA(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        x=fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}

2. Query, modify some path

void boom(int x,int y,int d){
    while(top[x]!=top[y]){      
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        update(1,li[top[x]],li[x],d);//修改时:ans+=query();
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    update(1,li[x],li[y],d);//修改时:ans+=query();
}

part3

Amway cross-section of a tree Blog .

Second, Fenwick tree, common operating segment tree

Ⅰ. Fenwick tree

Related blog: Fenwick tree (including Premium)

Ordinary tree array support:

+ 0. modified single-point single point of inquiry(Ordinary arrays on it 2333)

1. Single point update interval sum +

2. Update Interval + single point evaluated (using differential)

3. The single-point update request + prefixed maximum value (the value must be modified to satisfy exhibits monotonicity )


Ⅱ. Tree line

Related operations not one more elaborated. Here to distinguish between this question in coverage and modify (understood as an increase in value) operation.

Different meaning lazy mark nodes: part1

Covering the operation and modify operations are required to play a lazy mark, but the meaning and usage is different.

For more common modification operations, \ (lazy \) is used to his son downstream need to increase the cumulative value. Node \ (O \) represents \ ([b [o] .l , b [o] .r] \) this entire interval integration information;

For overwriting, \ (the lazy \) used to mark the value interval assigned to this, and it before the tree looks like does not matter. For non-leaf node node \ (o \) is itself no specific meaning.

part2: realization

We know that when modifying operating in a normal range:

Build : at the outset achievements \ (lazy \) on the values 0 , expressed the need to son under the cumulative value of 0;

update: For the interval \ ([ql, qr] \ ) of the modification operation, the value is included nodes \ (W \) increases a value, lazy flag \ (the lazy \) increases a value (depending on the specific operation problems may be);

down: For a node \ (O \) of the downstream operations, the left and right son \ (W \) increases a value, lazy flag \ (the lazy \) increases a value.

As for the range of coverage, the beginning if a contribution can not be directly assigned to 0 (if there is an assignment of 0 for the operator, it is heavier), we can be assigned to a subsequent operation will not cover the value, for example: If you only cover a natural number section, then you can \ (the lazy \) initially assigned -1. The next operation should not be a corresponding increase , but the assignment .

part3: contains a modified segment interval coverage problems +

You can refer to this Blog .

In fact, the nature of the same, open two marks, according to the classification to talk about.

Guess you like

Origin www.cnblogs.com/Tieechal/p/11468990.html