【2019/02/18测试T3】飘雪圣域

【题目】

传送门

题目描述:

IcePrincess_1968IcePrince_1968 长大了,他们开始协助国王 IceKing_1968 管理国内事物。

IcePrincess_1968IcePrince_1968 住在一个宁静悠远的王国:IceKingdom —— 飘雪圣域。飘雪圣域有 n n 个城镇,编号 1 , 2 , 3 , . . . , n 1,2,3,...,n 。有些城镇之间有道路,且满足任意两点之间有且仅有一条路径。飘雪圣域风景优美,但气候并不是太好。根据 IcePrince_1968 的气候探测仪,将来会发生 q q 场暴风雪。每场暴风雪可以用两个整数 l i , r i l_i,r_i 刻画,表示这场暴风雪之后,只有编号属于 [    l i    ,    r i    ] [\;l_i\;,\;r_i\;] 的城市没有受到暴风雪的影响。

在暴风雪的影响下迅速确定王国的农业生产方案是非常重要的事情。IceKing_1968 认为,一个农业生产地域应该是一个极大连通块,满足每个节点都没有被暴风雪影响。这里极大连通块的定义是:不存在一个不属于该点集的未被暴风雪影响的点与该连通块连通。

IcePrincess_1968 要负责算出每次暴风雪后,王国能拥有多少个农业生产地域。注意这里每次暴风雪是独立的,即每次暴风雪过后,直到每个城镇重新焕发生机,下一次暴风雪才会到来。

正如上文所述,IcePrincess_1968 擅长文学但不擅长计算机,于是请你帮忙。

输入格式:

第一行包含两个正整数 n , q n,q ,表示 IceKingdom 的城镇个数和暴风雪次数。

​第 2 2 至第 n n 行,每行两个正整数 x , y x,y ,表示城镇 x x 和城镇 y y 之间有一条道路。

​ 第 n + 1 n+1 至第 n + q n+q 行,每行两个正整数 l i , r i l_i,r_i ,描述一场暴风雪,含义如题面所述。

输出格式:

输出文件共有 q q 行,第 i i 行表示在第 i i 场暴风雪之后农业生产地域的个数。

样例数据:

输入
4 3
1 2
2 3
2 4
1 2
1 3
3 4

输出
1
1
2

提示:

【输入输出样例 1 1 解释】

​第一次询问,只有 ( 1 , 2 ) (1,2) 一个连通块。

​第二次询问,只有 ( 1 , 2 , 3 ) (1,2,3) 一个连通块。

​第三次询问,有 3 3 4 4 两个连通块。

【数据规模】

对于 30 % 30\% 的数据: n 100 n\le100 q 100 q\le100

对于 50 % 50\% 的数据: n 2 , 000 n\le2,000 q 2 , 000 q\le2,000

对于 100 % 100\% 的数据: n 200 , 000 n\le200,000 q 200 , 000 q\le200,000 ,对于所有的暴风雪, l i r i l_i\le r_i


【分析】

事实上,我们可以把这道题转换一下。

对于一条边 ( u , v ) (u,v) ,如果 u u v v 两个点都没有被影响,就称 ( u , v ) (u,v) 为好边。

那么每一条好边都可以使两端点所在的连通块连接起来,使总连通块个数 1 -1

因此假如有 n u m num 条好边,对于询问 [    l i    ,    r i    ] [\;l_i\;,\;r_i\;] 的答案就是 r i l i + 1 n u m r_i-l_i+1-num

对于一条边 ( u , v ) (u,v) ,我们不妨令 u < v u<v

那么,我们相当于是求满足 l i u < v r i l_i\le u<v\le r_i 的边的条数。

那我们把询问离线下来,用一个树状数组解决就行了。


【代码】

#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;
}

猜你喜欢

转载自blog.csdn.net/forever_dreams/article/details/87625659
T3