【提高测试】飘雪圣域(树状数组)

描述
​ IcePrincess_1968 和 IcePrince_1968 长大了,他们开始协助国王 IceKing_1968 管理国内事物。
​ IcePrincess_1968 和 IcePrince_1968 住在一个宁静悠远的王国:IceKingdom —— 飘雪圣域。飘雪圣域有 nn 个城镇,编号 1,2,3…n1,2,3…n。有些城镇之间有道路,且满足任意两点之间有且仅有一条路径。飘雪圣域风景优美,但气候并不是太好。根据 IcePrince_1968 的气候探测仪,将来会发生 qq 场暴风雪。每场暴风雪可以用两个整数 li,rili,ri刻画,表示这场暴风雪之后,只有编号属于[li,ri][li,ri]的城市没有受到暴风雪的影响。
​ 在暴风雪的影响下迅速确定王国的农业生产方案是非常重要的事情。IceKing_1968 认为,一个农业生产地域应该是一个极大连通块,满足每个节点都没有被暴风雪影响。这里极大连通块的定义是:不存在一个不属于该点集的未被暴风雪影响的点与该连通块连通。
​ IcePrincess_1968 要负责算出每次暴风雪后,王国能拥有多少个农业生产地域。注意这里每次暴风雪是独立的,即每次暴风雪过后,直到每个城镇重新焕发生机,下一次暴风雪才会到来。
​ 正如上文所述,IcePrincess_1968 擅长文学但不擅长计算机,于是请你帮忙。
输入
第一行包含两个正整数 n,qn,q,表示 IceKingdom 的城镇个数和暴风雪次数。
​ 第 22 至第 nn 行,每行两个正整数 x,yx,y,表示城镇 xx 和城镇 yy 之间有一条道路。
​ 第 n+1n+1 至第 n+qn+q 行,每行两个正整数 li,rili,ri,描述一场暴风雪,含义如题面所述。
输出
输出文件共有 qq 行,第 ii 行表示在第 ii 场暴风雪之后农业生产地域的个数。
样例输入
4 3
1 2
2 3
2 4
1 2
1 3
3 4
样例输出
1
2
提示
【输入输出样例 1 解释】
​ 第一次询问,只有(1,2)一个连通块。
​ 第二次询问,只有(1,2,3)一个连通块。
​ 第三次询问,有 3 和 4 两个连通块。
【数据规模】
对于 30%的数据:n<=100,q<=100n<=100,q<=100;
对于 50%的数据:n<=2,000,q<=2,000n<=2,000,q<=2,000;
对于 100%的数据:n<=200,000,q<=200,000n<=200,000,q<=200,000,对于所有的暴风雪,li<=rili<=ri。

考试的时候傻了,看完发现这题贼简单

可以发现如果有numnumnum条边不受暴风雪影响,答案就是r−l+1−numr-l+1-numrl+1num

不被影响的就是满足l≤u<v≤rl\le u<v \le rlu<vr的边(u,v)(u,v)(u,v)
对一维排序后树状数组随便维护一下就可以了

#include
using namespace std;
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*f;
} 
const int N=200005;
int tr[N],n,m,ans[N];
struct Str{
	int l,r,idx;
}e[N],q[N];
inline int lowbit(int x){
	return x&(-x);
}
inline void update(int p,int k){
	for(;p<=n;p+=lowbit(p))tr[p]+=k;
}
inline int query(int p,int res=0){
	for(;p;p-=lowbit(p))res+=tr[p];return res;
}
inline bool comp(const Str&a,const Str&b){
	return a.r<b.r;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<n;i++){
		e[i].l=read(),e[i].r=read();
		if(e[i].l>e[i].r)swap(e[i].l,e[i].r);
	}
	for(int i=1;i<=m;i++){
		q[i].l=read(),q[i].r=read(),q[i].idx=i;
	}
	sort(e+1,e+n,comp),sort(q+1,q+m+1,comp);
	int j=1;
	for(int i=1;i<=m;i++){
		while(q[i].r>=e[j].r&&j<n)update(e[j].l,1),j++;
		int tmp=query(q[i].r)-query(q[i].l-1);
		ans[q[i].idx]=q[i].r-q[i].l+1-tmp;
	}
	for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
}

转载于:https://www.cnblogs.com/stargazer-cyk/p/11145666.html

你可能感兴趣的:(【提高测试】飘雪圣域(树状数组))