• CF538H Summer Dichotomy题解


    题目链接: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;
    }
    
  • 相关阅读:
    opencv打开摄像头
    错误C2280 “std::_Hash<std::_Uset_traits<_Kty,std::_Uhash_compare<_Kty,_Hasher,_Keyeq>,_
    QPainter 画点
    错误 C1128 节数超过对象文件格式限制: 请使用 /bigobj 进行编译
    计算关节夹角
    osg绘制闭合曲线
    python opencv 把多张图片合成视频
    matplotlib动态图
    java File renameTo
    qt.qpa.xcb: could not connect to display
  • 原文地址:https://www.cnblogs.com/y-dove/p/14833172.html
Copyright © 2020-2023  润新知