题目大意:给出一棵树,一开始每两个点之间都是由土路连接的,但是会有一些土路逐渐变成公路,问每次从点1开始到点k有多少土路。
思路:POI不怎么难的题,实际上每个点到1的土路的数量就是这个点的深度,在土路变成公路的时候,这个点以及子树的所有节点的深度都要-1,子树修改就很基本了,可以用DFS序+fenwick,当然要是不嫌麻烦也可以树链剖分,但是常数会比较卡。。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 250010
using namespace std;
int points,asks;
int head[MAX],total;
int _next[MAX << 1],aim[MAX << 1];
int deep[MAX],cnt;
pair<int,int> range[MAX];
int fenwick[MAX];
char c[10];
inline void Add(int x,int y)
{
_next[++total] = head[x];
aim[total] = y;
head[x] = total;
}
void DFS(int x,int last)
{
deep[x] = deep[last] + 1;
range[x].first = ++cnt;
for(int i = head[x]; i; i = _next[i]) {
if(aim[i] == last) continue;
DFS(aim[i],x);
}
range[x].second = cnt;
}
inline void Fix(int x,int c)
{
for(; x; x -= x&-x)
fenwick[x] -= c;
}
inline int GetSum(int x)
{
int re = 0;
for(; x <= points; x += x&-x)
re += fenwick[x];
return re;
}
int main()
{
cin >> points;
for(int x,y,i = 1; i < points; ++i) {
scanf("%d%d",&x,&y);
Add(x,y),Add(y,x);
}
deep[0] = -1;
DFS(1,0);
cin >> asks;
for(int x,y,i = 1; i <= asks + points - 1; ++i) {
scanf("%s",c);
if(c[0] == 'A') {
scanf("%d%d",&x,&y);
int opt = deep[x] > deep[y] ? x:y;
Fix(range[opt].first - 1,1);
Fix(range[opt].second,-1);
}
else {
scanf("%d",&x);
printf("%d\n",deep[x] - GetSum(range[x].first));
}
}
return 0;
}BZOJ 1103 POI 2007 大都市meg 树状数组
原文地址:http://blog.csdn.net/jiangyuze831/article/details/41410063