【题目】
题目描述:
IcePrincess_1968 和 IcePrince_1968 长大了,他们开始协助国王 IceKing_1968 管理国内事物。
IcePrincess_1968 和 IcePrince_1968 住在一个宁静悠远的王国:IceKingdom —— 飘雪圣域。飘雪圣域有 个城镇,编号 。有些城镇之间有道路,且满足任意两点之间有且仅有一条路径。飘雪圣域风景优美,但气候并不是太好。根据 IcePrince_1968 的气候探测仪,将来会发生 场暴风雪。每场暴风雪可以用两个整数 刻画,表示这场暴风雪之后,只有编号属于 的城市没有受到暴风雪的影响。
在暴风雪的影响下迅速确定王国的农业生产方案是非常重要的事情。IceKing_1968 认为,一个农业生产地域应该是一个极大连通块,满足每个节点都没有被暴风雪影响。这里极大连通块的定义是:不存在一个不属于该点集的未被暴风雪影响的点与该连通块连通。
IcePrincess_1968 要负责算出每次暴风雪后,王国能拥有多少个农业生产地域。注意这里每次暴风雪是独立的,即每次暴风雪过后,直到每个城镇重新焕发生机,下一次暴风雪才会到来。
正如上文所述,IcePrincess_1968 擅长文学但不擅长计算机,于是请你帮忙。
输入格式:
第一行包含两个正整数 ,表示 IceKingdom 的城镇个数和暴风雪次数。
第 至第 行,每行两个正整数 ,表示城镇 和城镇 之间有一条道路。
第 至第 行,每行两个正整数 ,描述一场暴风雪,含义如题面所述。
输出格式:
输出文件共有 行,第 行表示在第 场暴风雪之后农业生产地域的个数。
样例数据:
输入
4 3
1 2
2 3
2 4
1 2
1 3
3 4
输出
1
1
2
提示:
【输入输出样例 解释】
第一次询问,只有 一个连通块。
第二次询问,只有 一个连通块。
第三次询问,有 和 两个连通块。
【数据规模】
对于 的数据: , ;
对于 的数据: , ;
对于 的数据: , ,对于所有的暴风雪, 。
【分析】
事实上,我们可以把这道题转换一下。
对于一条边 ,如果 和 两个点都没有被影响,就称 为好边。
那么每一条好边都可以使两端点所在的连通块连接起来,使总连通块个数 。
因此假如有 条好边,对于询问 的答案就是 。
对于一条边 ,我们不妨令 。
那么,我们相当于是求满足 的边的条数。
那我们把询问离线下来,用一个树状数组解决就行了。
【代码】
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define N 200005
#define lowbit(x) (x&-x)
#define Pair pair<int,int>
using namespace std;
vector<int>E[N];
vector<Pair>Q[N];
int n,q,bit[N],ans[N];
void add(int i,int x)
{
for(;i<=n;i+=lowbit(i)) bit[i]+=x;
}
int query(int i)
{
int ans=0;
for(;i;i-=lowbit(i)) ans+=bit[i];
return ans;
}
int main()
{
int x,y,i,j;
scanf("%d%d",&n,&q);
for(i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
if(x>y) swap(x,y);
E[y].push_back(x);
add(x,1);
}
for(i=1;i<=q;++i)
{
scanf("%d%d",&x,&y);
Q[y].push_back(make_pair(x,i));
}
for(i=n;i;--i)
{
for(j=0;j<Q[i].size();++j)
{
int sum=query(i)-query(Q[i][j].first-1);
ans[Q[i][j].second]=(i-Q[i][j].first+1)-sum;
}
for(j=0;j<E[i].size();++j) add(E[i][j],-1);
}
for(i=1;i<=q;++i)
printf("%d\n",ans[i]);
return 0;
}