树状数组

bzoj 1103 [POI2007]大都市

描述

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

输入

第一行是一个数 n.
以下 n-1 行,每行两个整数 a,b(1<=a<b<=n),表示改造开始之前有一条土路连接着村庄 a 和村庄 b.
以下一行包含一个整数 m,表示 Blue Mary 曾经在改造期间送过 m 次信。
以下 n+m-1 行,每行有两种格式的若干信息,表示按时间先后发生过的 n+m-1次事件:
若这行为 A a b(1<=a<b<=n),则表示城市 a,b 之间的土路被改成公路,保证不会重复;
若这行为 W a, 则表示 Blue Mary 曾经从比特堡送信到村庄 a。

输出

有 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
1
0
1

提示

1<= N , M <=100000


这又是什么鬼翻译
显然题目给出了一棵树,并在树上进行了查询和修改操作。
所以可以用树状数组解决。
X入栈时栈内的点是 1 到 X 的路径上的点。
以 1 为根进行 DFS,每个点(1 除外)入栈时向序列中加一个 1,出栈时加入一个-1。
对于修改,我们将较深点对应的权值变为0(即入栈时加-1,出栈时加1);
对于查询,设 X 入栈位置为 a,那么 1 到 X 的距离为树状数组前 a 个元素的和。
然而我考试时竟然把树状数组写炸了
代码蒯上

#include<iostream>
#include<iomanip>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gotcha()
{
	register int _a=0;bool _b=1;register char _c=getchar();
	while(_c<'0' || _c>'9'){if(_c=='-')_b=0;_c=getchar();}
	while(_c>='0' && _c<='9')_a=_a*10+_c-48,_c=getchar();
	return _b?_a:-_a;
}
const int _ = 100002;
struct edge{int to,ne;edge(){to=ne=0;}}e[_];
int he[_]={0},ecnt=0;
void add(int fr,int to){e[++ecnt].to=to,e[ecnt].ne=he[fr],he[fr]=ecnt;}
int t[_]={0},in[_]={0},out[_]={0},n,m,cnt=0;
#define lb(x) ((x)&(-(x)))
void undo(int d,int num){while(d<=n)t[d]+=num,d+=lb(d);}
int finder(int d){int sum=0;while(d)sum+=t[d],d-=lb(d);return sum;}
void DFS(int d)
{
	out[d]=1,in[d]=++cnt;
	for(int i=he[d];i;i=e[i].ne)DFS(e[i].to),out[d]+=out[e[i].to];
	undo(in[d],1),undo(in[d]+out[d],-1);
}
int main()
{
	register int i,a,b;char ch[6];
	n=gotcha();
	for(i=1;i<n;i++)a=gotcha(),b=gotcha(),add(min(a,b),max(a,b));
	DFS(1),undo(1,-1),undo(n+1,1);
	m=gotcha()+n-1;
	while(m--)
	{
		scanf("%s",ch),a=gotcha();
		if(ch[0]=='W')printf("%d
",finder(in[a]));
		else b=max(a,gotcha()),undo(in[b],-1),undo(in[b]+out[b],1);
	}
	return 0;
}

记住以后读字符指令都要用字符串读!否则每次都读入一些奇怪的东西

原文地址:https://www.cnblogs.com/finder-iot/p/7619831.html