1106

A 题比较水 贪心一下就可以了
B 题树形DP+换根 方程也很好推 但是我写了之后调了很久大样例一直过不了 没有想到利用暴力去拍小数据 静态差错了好久 一发小样例就知道哪里出问题了.....
C 题 确实没有想到 所以我着重来说下C题
首先对于扑克等的应该想到建图 一张卡牌对应一条边
建图后发现如果满足树的条件则不能遍历一颗树 所以想到利用并查集维护联通性 对于满足树形结构的 肯定不能遍历最大与最小
所以在并查集合上维护集合的最大最小值就行了 然后利用后缀最小值 查找影响的范围
如果对于一段[l,r]的询问 找到l的后缀最小值x 如果x<=r就行不通 反之就行
查找后缀最小值及其修改的时候利用了树状数组
code:

//
#include<bits/stdc++.h>
using namespace std;
#define maxnn (int)(2e5)
int c[maxnn];
int s[maxnn][3];
int MIN[maxnn],MAX[maxnn];
int n,k;
int f[maxnn];
#define lowbit(i) i&(-i)
void add(int x,int y) {
	for(int i=x; i; i-=lowbit(i)) {
		c[i]=min(c[i],y);
	}
}
int get(int x) {
	int ans=10000000;
	for(int i=x; i<=n; i+=lowbit(i)) {
		ans=min(c[i],ans);
	}
	return ans;
}
int gf(int v) {
	return f[v]==v?v:f[v]=gf(f[v]);
}
#define GC getchar()
inline int  R() {
	char t;
	int f=1;
	int x=0;
	t=GC;
	while(!isdigit(t)) {
		if(t=='-') f=-1;
		t=GC;
	}
	while(isdigit(t)) {
		x=x*10+t-48;
		t=GC;
	}
	return x*f;
}
int main() {
	memset(c,1000000,sizeof(c));
	n=R();
	k=R();
	for(int i=1; i<=1e5; i++) {
		f[i]=i;
		s[i][1]=1;
		MIN[i]=i;
		MAX[i]=i;
	}
	int x,y;
	for(int i=1; i<=k; i++) {
		x=R();
		y=R();
		int fx=gf(x);
		int fy=gf(y);
		if(fx==fy) {
			s[gf(x)][0]++;
		} else {
			s[gf(y)][1]+=s[gf(x)][1];
			s[gf(y)][0]+=s[gf(x)][0];
			s[gf(y)][0]++;
			MIN[fy]=min(MIN[fx],MIN[fy]);
			MAX[fy]=max(MAX[fx],MAX[fy]);
			f[fx]=fy;
		}
	}
	for(int i=1; i<=n; i++) {
		if(f[i]==i) {
			if(s[i][0]<s[i][1]) add(MIN[i],MAX[i]);
		}
	}
	int q;
	cin>>q;
	while(q--) {
		cin>>x>>y;
		if(get(x)<=y) {
			puts("No");
		} else {
			puts("Yes");
		}
	}
}
原文地址:https://www.cnblogs.com/OIEREDSION/p/11805748.html