Grass Planting GRASS AND TREE CHAIN PARTITION OF [USACO 2011 December Gold]

Title Description

Farmer John has N barren pastures (2 <= N <== 100,000), and N-1 two-way road links the N pastures, each with only one path to each other. Bessie, a famous cow, often complains: Why is there no grass on the road connecting the pasture?
John likes Bessie very much. Today John finally decided to plant grass on the road. John's weeding was divided into M (1 <= M <= 100,000) steps.
In each step, one of the following two events occurs:
1. John will choose two pastures, along the path between the two pastures, and plant one grass on each road along the path.
2. Bessie will ask John how many forages were planted on a designated road.
Please help John answer Bessie's question.

The main idea of the topic

Realize two operations: from u-v path edge right + 1, ask from u-v path edge right.

Data range

(1 <= M <=100,000)
(2 <= N <= 100,000)

sample input

4 6
1 4
2 4
3 4
P 2 3
P 1 3
Q 3 4
P 1 4
Q 2 4
Q 1 4

sample output

2
1
2

Solving problems

Tree Chain Partitioning Template Question

Code

#include <bits/stdc++.h>
#define Maxn 100005
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
inline char Getch(){char ch=getchar();while(ch!='P'&&ch!='Q')ch=getchar();return ch;}
struct NODE{int to,next;}e[Maxn*2];
struct node{int L,r,Sum,Add;}Tree[Maxn*4];
int n,q,cnt=0,dep[Maxn],size[Maxn],son[Maxn],mark[Maxn],fa[Maxn],top[Maxn],h[Maxn];
void AddEdge(int x,int y){e[++cnt]=(NODE){y,h[x]};h[x]=cnt;}
void dfs1(int x,int L,int d){
    int Max=0;
    dep[x]=d;
    size[x]=1;
    son[x]=0;
    for(int p=h[x];p;p=e[p].next){
        int y=e[p].to;
        if(y==L)continue;
        dfs1(y,x,d+1);
        fa[y]=x;
        size[x]+=size[y];
        if(size[y]>Max){
            Max=size[y];
            son[x]=y;
        }
    }
}
void dfs2(int x,int L){
    top[x]=L;
    mark[x]=++cnt;
    if(son[x])dfs2(son[x],L);
    for(int p=h[x];p;p=e[p].next)
        if(e[p].to!=fa[x]&&e[p].to!=son[x])
            dfs2(e[p].to,e[p].to);
}
void PushDown(int v){
    Tree[2*v].Add+=Tree[v].Add;
    Tree[2*v+1].Add+=Tree[v].Add;
    Tree[2*v].Sum+=Tree[v].Add*(Tree[2*v].r-Tree[2*v].L+1);
    Tree[2*v+1].Sum+=Tree[v].Add*(Tree[2*v+1].r-Tree[2*v+1].L+1);
    Tree[v].Add=0;
}
void PushUp(int v){
    Tree[v].Sum=Tree[2*v].Sum+Tree[2*v+1].Sum;
}
void Build(int v,int L,int r){
    Tree[v]=(node){L,r,0,0};
    if(L==r)return;
    Build(2*v,L,(L+r)/2);
    Build(2*v+1,(L+r)/2+1,r);
}
long long Ask(int v,int L,int r){
    if(r<Tree[v].L||Tree[v].r<L)return 0;
    if(L<=Tree[v].L&&Tree[v].r<=r)return Tree[v].Sum;
    PushDown(v);
    return Ask(2*v,L,r)+Ask(2*v+1,L,r);
}
void Modify(int v,int L,int r){
    if(r<Tree[v].L||Tree[v].r<L)return;
    if(L<=Tree[v].L&&Tree[v].r<=r){
        Tree[v].Sum+=(Tree[v].r-Tree[v].L+1);
        Tree[v].Add++;
        return;
    }
    PushDown(v);
    Modify(2*v,L,r);
    Modify(2*v+1,L,r);
    PushUp(v);
}
int main(){
    n=Getint();q=Getint();
    for(int i=1;i<n;i++){
        int x=Getint(),y=Getint();
        AddEdge(x,y);
        AddEdge(y,x);
    }
    cnt=0;
    dfs1(1,0,1);
    dfs2(1,1);
    Build(1,1,cnt);
    while(q--){
        char ch=Getch();
        if(ch=='Q'){
            int L=Getint(),r=Getint(),f1=top[L],f2=top[r];
            int Ans=0;
            while(f1!=f2){
                if(dep[f1]<dep[f2])swap(f1,f2),swap(L,r);
                Ans+=Ask(1,mark[f1],mark[L]);
                L=fa[f1];
                f1=top[L];
            }
            if(L!=r){
                if(dep[L]>dep[r])swap(L,r);
                Ans+=Ask(1,mark[son[L]],mark[r]);
            }
            cout<<Ans<<"\n";
        }else{
            int L=Getint(),r=Getint(),f1=top[L],f2=top[r];
            while(f1!=f2){
                if(dep[f1]<dep[f2])swap(f1,f2),swap(L,r);
                Modify(1,mark[f1],mark[L]);
                L=fa[f1];
                f1=top[L];
            }
            if(L!=r){
                if(dep[L]>dep[r])swap(L,r);
                Modify(1,mark[son[L]],mark[r]);
            }
        }
    }
    return 0;
}

Posted by aerodromoi on Mon, 11 Feb 2019 22:45:18 -0800