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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章