题目描述
Farmer John has
N
barren pastures (
At each step one of two things will happen:
1. FJ will choose two pastures, and plant a patch of grass along each road in between the two pastures, or,
2. Bessie will ask about how many patches of grass on a particular road, and Farmer John must answer her question.
Farmer John is a very poor counter – help him answer Bessie’s questions!
给出一棵
n
个节点的树,有
输入格式
Line 1: Two space-separated integers
N
and
Lines 2..
N
: Two space-separated integers describing the endpoints of a road.
Lines
输出格式
Lines 1..???: Each line has the answer to a query, appearing in the same order as the queries appear in the input.
输入样例#1
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
输出样例#1
2
1
2
思路
树链剖分入门题。不会树链剖分?请看本人的另一篇博客:[ZJOI2008]树的统计。
代码
#include <cstdio>
#include <algorithm>
const int maxn=100000;
struct sigment_tree
{
int val[(maxn<<2)+10],lazy[(maxn<<2)+10];
int updata(int now)
{
val[now]=val[now<<1]+val[now<<1|1];
return 0;
}
int pushdown(int now,int left,int right)
{
int mid=(left+right)>>1;
lazy[now<<1]+=lazy[now];
val[now<<1]+=(mid-left+1)*lazy[now];
lazy[now<<1|1]+=lazy[now];
val[now<<1|1]+=(right-mid)*lazy[now];
lazy[now]=0;
return 0;
}
int build(int now,int left,int right)
{
if(left==right)
{
val[now]=0;
lazy[now]=0;
return 0;
}
int mid=(left+right)>>1;
build(now<<1,left,mid);
build(now<<1|1,mid+1,right);
updata(now);
return 0;
}
int change(int now,int left,int right,int askl,int askr,int addval)
{
if((right<askl)||(askr<left))
{
return 0;
}
if((askl<=left)&&(askr>=right))
{
lazy[now]+=addval;
val[now]+=(right-left+1)*addval;
return 0;
}
int mid=(left+right)>>1;
pushdown(now,left,right);
change(now<<1,left,mid,askl,askr,addval);
change(now<<1|1,mid+1,right,askl,askr,addval);
updata(now);
return 0;
}
int ask(int now,int left,int right,int askl,int askr)
{
if((right<askl)||(askr<left))
{
return 0;
}
if((askl<=left)&&(askr>=right))
{
return val[now];
}
int mid=(left+right)>>1;
pushdown(now,left,right);
return ask(now<<1,left,mid,askl,askr)+ask(now<<1|1,mid+1,right,askl,askr);
}
};
int n,m;
struct tree
{
int pre[(maxn<<1)+10],now[maxn+10],son[(maxn<<1)+10],tot;
int deep[maxn+10],dfn[maxn+10],cnt,fa[maxn+10],wson[maxn+10],top[maxn+10],size[maxn+10];
sigment_tree st;
int ins(int a,int b)
{
tot++;
pre[tot]=now[a];
now[a]=tot;
son[tot]=b;
return 0;
}
int first_dfs(int u,int father)
{
deep[u]=deep[father]+1;
fa[u]=father;
size[u]=1;
int j=now[u];
while(j)
{
int v=son[j];
if(v!=father)
{
first_dfs(v,u);
size[u]+=size[v];
if((!wson[u])||(size[wson[u]]<size[v]))
{
wson[u]=v;
}
}
j=pre[j];
}
return 0;
}
int second_dfs(int u,int father,int topfather)
{
cnt++;
dfn[u]=cnt;
top[u]=topfather;
if(wson[u])
{
second_dfs(wson[u],u,topfather);
}
int j=now[u];
while(j)
{
int v=son[j];
if((v!=father)&&(v!=wson[u]))
{
second_dfs(v,u,v);
}
j=pre[j];
}
return 0;
}
int change(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
{
std::swap(x,y);
}
st.change(1,1,n,dfn[top[x]],dfn[x],1);
x=fa[top[x]];
}
if(deep[x]>deep[y])
{
std::swap(x,y);
}
st.change(1,1,n,dfn[wson[x]],dfn[y],1);
return 0;
}
int ask(int x,int y)
{
int res=0;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
{
std::swap(x,y);
}
res+=st.ask(1,1,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(deep[x]>deep[y])
{
std::swap(x,y);
}
res+=st.ask(1,1,n,dfn[wson[x]],dfn[y]);
return res;
}
};
tree t;
int main()
{
freopen("grass.in","r",stdin);
freopen("grass.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
t.ins(a,b);
t.ins(b,a);
}
t.st.build(1,1,n);
t.first_dfs(1,0);
t.second_dfs(1,0,1);
for(int i=1; i<=m; i++)
{
char opt[10];
int x,y;
scanf("%s%d%d",opt,&x,&y);
if(opt[0]=='P')
{
t.change(x,y);
}
else
{
printf("%d\n",t.ask(x,y));
}
}
return 0;
}