1103: [POI2007]大都市meg

来源:互联网 发布:数控折弯机编程方法 编辑:程序博客网 时间:2024/05/20 11:47

Description

  在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了。
不过,她经常回忆起以前在乡间漫步的情景。昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双
向的土路。从每个村庄都恰好有一条路径到达村庄1(即比特堡)。并且,对于每个村庄,它到比特堡的路径恰好
只经过编号比它的编号小的村庄。另外,对于所有道路而言,它们都不在除村庄以外的其他地点相遇。在这个未开
化的地方,从来没有过高架桥和地下铁道。随着时间的推移,越来越多的土路被改造成了公路。至今,Blue Mary
还清晰地记得最后一条土路被改造为公路的情景。现在,这里已经没有土路了——所有的路都成为了公路,而昔日
的村庄已经变成了一个大都市。 Blue Mary想起了在改造期间她送信的经历。她从比特堡出发,需要去某个村庄,
并且在两次送信经历的间隔期间,有某些土路被改造成了公路.现在Blue Mary需要你的帮助:计算出每次送信她需
要走过的土路数目。(对于公路,她可以骑摩托车;而对于土路,她就只好推车了。)

Input

  第一行是一个数n(1 < = n < = 2 50000).以下n-1行,每行两个整数a,b(1 < =  a以下一行包含一个整数m
(1 < = m < = 2 50000),表示Blue Mary曾经在改造期间送过m次信。以下n+m-1行,每行有两种格式的若干信息
,表示按时间先后发生过的n+m-1次事件:若这行为 A a b(a若这行为 W a, 则表示Blue Mary曾经从比特堡送信到
村庄a。

Output

  有m行,每行包含一个整数,表示对应的某次送信时经过的土路数目。

Sample Input

5
1 2
1 3
1 4
4 5
4
W 5
A 1 4
W 5
A 4 5
W 5
W 2
A 1 2
A 1 3

Sample Output

      2
   1
   0
   1

树链剖分求1到a的距离,感觉没必要搞得这么麻烦。

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>using namespace std;const int maxm = 250005;const int INF = 1000005;#define swap(a,b){int temp=a;a=b;b=temp;}struct node{int sum, Max, l, r;}tr[maxm * 4];vector<int>v[maxm];int val[maxm], link[maxm], tot, fa[maxm], son[maxm], top[maxm], s[maxm], dep[maxm], n, w[maxm];void dfs_1(int k, int pre, int ndep);void dfs_2(int k, int pre, int ntop);void make(int num, int a, int b);void update(int num, int id, int xx);int qsum(int num, int a, int b);int getsum(int l, int r);int main(){char str[12];int q, i, x, y;scanf("%d", &n);for (i = 1;i < n;i++){scanf("%d%d", &x, &y);v[x].push_back(y);v[y].push_back(x);}for (i = 2;i <= n;i++)val[i] = 1;dfs_1(1, 0, 1);dfs_2(1, 0, 1);make(1, 1, n);scanf("%d", &q);for (i = 1;i <= n + q - 1;i++){scanf("%s", str);if (str[0] == 'W'){scanf("%d", &x);printf("%d\n", getsum(1, x));}else{scanf("%d%d", &x, &y);if (x > y)swap(x, y);update(1, w[y], 0 - val[y]);val[y] = 0;}}return 0;}void dfs_1(int k, int pre, int ndep){dep[k] = ndep, fa[k] = pre;s[k] = 1;for (int i = 0;i < v[k].size();i++){int xx = v[k][i];if (xx == pre)continue;dfs_1(xx, k, ndep + 1);s[k] += s[xx];if (son[k] == 0 || s[xx] > s[son[k]])son[k] = xx;}}void dfs_2(int k, int pre, int ntop){tot++;top[k] = ntop;w[k] = tot;link[tot] = k;if (son[k] == 0)return;dfs_2(son[k], k, ntop);for (int i = 0;i < v[k].size();i++){int xx = v[k][i];if (xx == pre || xx == son[k]) continue;dfs_2(xx, k, xx);}}void make(int num, int a, int b){tr[num].l = a, tr[num].r = b;if (a == b){tr[num].sum = val[link[a]];return;}int mid = (a + b) / 2;make(num * 2, a, mid);make(num * 2 + 1, mid + 1, b);tr[num].sum = tr[num * 2].sum + tr[num * 2 + 1].sum;}void update(int num, int id, int xx){if (tr[num].l == tr[num].r){tr[num].sum += xx;return;}int mid = (tr[num].l + tr[num].r) / 2;if (mid >= id)update(num * 2, id, xx);else update(num * 2 + 1, id, xx);tr[num].sum = tr[num * 2].sum + tr[num * 2 + 1].sum;}int getsum(int l, int r){int ans = 0, f1, f2;f1 = top[l], f2 = top[r];while (f1 != f2){if (dep[f1] < dep[f2]){swap(f1, f2);swap(l, r);}ans += qsum(1, w[f1], w[l]);l = fa[f1], f1 = top[l]; }if (dep[l] > dep[r]) ans += qsum(1, w[r], w[l]);else ans += qsum(1, w[l], w[r]);return ans;}int qsum(int num, int a, int b){int ans = 0;if (tr[num].l >= a&&tr[num].r <= b)return tr[num].sum;int mid = (tr[num].l + tr[num].r) / 2;if (a <= mid) ans += qsum(num * 2, a, b);if (b > mid) ans += qsum(num * 2 + 1, a, b);return ans;}