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;
}