2018 ccpcfinal Gym - 102055B滑动窗口

题意问你 给你 n个人 每个人 有两种属性 可以选择 A 选择 B 但是有些人 不能同时选 A或者 同时选B 问最后得到的 MAX - MIN 最小

首先没有 人限制的话 那么就是个经典题 滑动窗口求 差值最小 只需要把两个值拆分 sort一下 然后每次找到 n 个人 的属性取一下 min 即可
有限制的话 无非是 把人变成了联通块 多个联通块 组合求差值 此题 是 每个人选择两种值 每个联通块就有两种 maxn 和 minn 我们只需要拆分成 4种值进行排序即可

#include<iostream>
#include<algorithm>
#include<cstring>
#define x first
#define y second

using namespace std;

const int N = 2e5 + 10,M = N * 2;
typedef pair<pair<int,int> ,pair<int,int> > PII;

struct node{
    
    
    int x,id,type;
    bool operator < (const node &p)const{
    
    
        return x < p.x;
    }
}c[M * 2];

int a[N],b[N];
int head[N],to[M],last[M],cnt;
void add(int a,int b){
    
    
    to[++cnt] = b;
    last[cnt] = head[a];
    head[a] = cnt;
}

bool flag;
int color[N];
PII get_color(int x,int pre){
    
    
    int maxn1 = a[x],minn1 = a[x];
    int maxn2 = b[x],minn2 = b[x];
    for(int i = head[x]; i != -1; i = last[i]){
    
    
        int j = to[i];
        if(pre == j) continue;
        if(color[j] == 3) color[j] = color[x] ^ 1;
        else{
    
    
            if(color[j] != (color[x] ^ 1)){
    
    
                flag = false;
                return {
    
    {
    
    0,0},{
    
    0,0}};
            }else continue;
        }
        PII p = get_color(j,x);
        maxn1 = max(maxn1,p.y.x);
        minn1 = min(minn1,p.y.y);
        maxn2 = max(maxn2,p.x.x);
        minn2 = min(minn2,p.x.y);
    }
    return {
    
    {
    
    maxn1,minn1},{
    
    maxn2,minn2}};
}
PII ve[N];

int st[N][3];

int main(){
    
    
    int t;
    cin >> t;
    int CASE = 0;
    while(t--){
    
    
        int n,m;
        cin >> n >> m;
        memset(st,0,sizeof st);
        memset(head,-1,sizeof head);
        flag = true;
        cnt = 0;
        for(int i = 1; i <= m; i++){
    
    
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }

        for(int i = 1; i <= n; i++){
    
    
            scanf("%d%d",&a[i],&b[i]);
        }
        for(int i = 1; i <= n; i++) color[i] = 3;

        int ans = 0;
        for(int i = 1; i <= n; i++){
    
    
            if(color[i] == 3){
    
    
                color[i] = 1;
                ve[++ans] = get_color(i,0);
            }else continue;
        }

        printf("Case %d: ",++CASE);
        if(!flag){
    
    
            printf("IMPOSSIBLE\n");
            continue;
        }

        int d = 0;
        for(int i = 1; i <= ans; i++){
    
    
            c[++d] = {
    
    ve[i].x.x,i,0};
            //cout << ve[i].x.x << " " << ve[i].x.y << " " << ve[i].y.x<< " " << ve[i].y.y << "asd" <<endl;
            c[++d] = {
    
    ve[i].x.y,i,0};
            c[++d] = {
    
    ve[i].y.x,i,1};
            c[++d] = {
    
    ve[i].y.y,i,1};
        }

        sort(c + 1,c + d + 1);

        int minn = 0x3f3f3f3f;
        int r = 1,s = 0;
        for(int i = 1; i <= d; i++){
    
    
            st[c[i - 1].id][c[i - 1].type]--;
            if(st[c[i - 1].id][c[i - 1].type] == 1 && st[c[i - 1].id][c[i - 1].type ^ 1] != 2) s--;
            while(r <= d && s < ans){
    
    
                st[c[r].id][c[r].type]++;
                if(st[c[r].id][c[r].type] == 2 && st[c[r].id][c[r].type ^ 1] != 2) s++;
                r++;
            }
            if(c[i].id == c[r - 1].id && c[i].type != c[r - 1].type) continue;
            if(s != ans) continue;
            minn = min(minn,c[r - 1].x - c[i].x);
        }

        cout << minn << endl;

    }





    return 0;
}

猜你喜欢

转载自blog.csdn.net/qqqingyi/article/details/120761952