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");
}
}
}