题目链接:CF538H
反思
刚开始执意想先跑二分图,然后计算n1,n2合法的区间,结果反而非常难以计算,其实稍一转弯,先计算n1,n2,再跑二分图,一切就明朗了许多
有些时候,如果有两种思考方法,不要死磕一种,两种都尝试一下
solution
-
设第一组人数为n1,第二组为n2
-
我们不妨先不考虑t,T的限制
-
考虑直接构造出n1,n2,我们不妨思考,如果所有区间都有交,那么所有老师都可以任意选择区间
-
否则必然是有两个区间无交(3个及以上直接无解),然后剩下所有区间都靠到两个区间上
-
我们不妨令(n2 = max{l_i},n1 = min{r_i}),注意这样能最大可能的包含所有合法情况
-
稍一画图便可知道,假设我们一直维护两个区间[l1,r1],[l2,r2]分别表示最终状态中,n1,n2可行的区间,则r1,l2始终不会改变,即为我们构造的n1,n2,会减小|增大的,只有l1,r2
-
那么接着考虑若(n1 + n2 < T)怎么办,注意到n1已经是区间右端点了,我们只可能增大n2,令(n2 = T - n1)
-
同理,若(n1 + n2 > t),令(n1 = t - n2)
-
得到n1,n2后,若有某个老师两个组都分不进去,无解,若某个老师只能分进某个组,提前确定,剩下的,待定,连边二分图染色即可
代码如下(n1,n2和题解描述的反过来了)
/*CF538H Summer Dichotomy*/
#include<bits/stdc++.h>
using namespace std;
int read(){
char c = getchar();
int x = 0;
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - 48,c = getchar();
return x;
}
int T,t,n;
const int _ = 1e6 + 7;
vector<int>E[_];
int lx,rx,ly,ry;
typedef pair<int,int> pii;
typedef pair<pii,pii> PII;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define fail return puts("IMPOSSIBLE"),0
pii p[_];
PII P[_];int cnt = 0;
int c[_];
bool in(pii A,int x){
int l = A.fi,r = A.se;
return x <= r && x >= l;
}
bool dfs(int u){
for(auto v:E[u]){
if(!c[v]){
c[v] = 3 - c[u];
if(!dfs(v)) return 0;
}
else if(c[v] == c[u]) return 0;
}
return 1;
}
int main(){
t = read(),T = read();
n = read();int m = read();
int n1 = 0,n2 = 1e9;
for(int i = 1; i <= n; ++i){
int l = read(),r = read();
p[i] = mp(l,r);
n1 = max(n1,l),n2 = min(n2,r);
}
if(n1 + n2 < t) n1 = t - n2;
if(n1 + n2 > T) n2 = T - n1;
// cout<<n1<<' '<<n2<<'
';
if(n1 < 0 || n2 < 0) fail;
for(int i = 1; i <= m; ++i){
int u = read(),v = read();
E[u].pb(v);E[v].pb(u);
}
for(int i = 1; i <= n; ++i){
bool o1 = in(p[i],n1);
bool o2 = in(p[i],n2);
if(!o1 && !o2) fail;
if(o1 && o2) continue;
if(o1) c[i] = 1;
else c[i] = 2;
}
for(int i = 1; i <= n; ++i){
if(c[i]){
if(!dfs(i)) fail;
}
}
for(int i = 1; i <= n; ++i){
if(!c[i]){
c[i] = 1;
if(!dfs(i)) fail;
}
}
puts("POSSIBLE");
cout<<n1<<' '<<n2<<'
';
for(int i = 1; i <= n; ++i) if(c[i] == 1) putchar('1');else putchar('2');
return 0;
}