cf 429e Points and Segments

题意:给1e5个区间(区间大小1e9,构造区间01染色,可否构造出每个点被染成0和被染成1的次数一样。
思路:

  1. 想通一点,不可能输出-1
  2. 差分,染色相当于a[l]++,a[r+1]–
  3. 设蓝+1,红-1,那么染蓝a[l]++,a[r+1]–;染红a[l]–,a[r+1]++
  4. 把差分问题转为建图,a[l]++,a[r+1]–变为从l到r+1的有向边,同理染红相反
  5. 问题可以转换为如何使得每个点入度和出度相差<=1
  6. 如果把所有奇度边相连那么只要跑欧拉回路就可以构造出来了,问题就转化为板子题了
  7. 注意离散

代码:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0)
const int maxn = 2e5+5;

int head[maxn],deg[maxn],ans[maxn],tot = 1;
struct edge{
    int v,nex,id;
    bool f;
}e[maxn<<4];
void add(int u,int v,int id){
    e[++tot] = {v,head[u],id,0},head[u] = tot;
    e[++tot] = {u,head[v],id,0},head[v] = tot;
}
struct Q{
    int l,r;
}q[maxn];
vector<int>a;
void euler(int u){
    for(int &i = head[u];i;i = e[i].nex){
        if(e[i].f) continue;
        e[i].f = e[i^1].f = 1;
        int v = e[i].v;
        ans[e[i].id] = (u<v);
        euler(v);
    }
}
int main(){
    IO;
    int n;cin>>n;
    forn(i,n){
        cin>>q[i].l>>q[i].r;
        q[i].r++;
        a.push_back(q[i].l);
        a.push_back(q[i].r);
    }
    sort(a.begin(),a.end());
    a.erase(unique(a.begin(),a.end()),a.end());
    forn(i,n){
        q[i].l = lower_bound(a.begin(),a.end(),q[i].l)-a.begin();
        q[i].r = lower_bound(a.begin(),a.end(),q[i].r)-a.begin();
        deg[q[i].l]++,deg[q[i].r]++;
        add(q[i].l,q[i].r,i);
    }
    int len = a.size(),last = -1;
    forn(i,len){
        if(deg[i]&1){
            if(last==-1) last = i;
            else add(last,i,n+3),last = -1;
        }
    }
    forn(i,len) if(head[i]) euler(i);
    forn(i,n) cout<<ans[i]<<' ';
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章