題意:給1e5個區間(區間大小1e9,構造區間01染色,可否構造出每個點被染成0和被染成1的次數一樣。
思路:
- 想通一點,不可能輸出-1
- 差分,染色相當於a[l]++,a[r+1]–
- 設藍+1,紅-1,那麼染藍a[l]++,a[r+1]–;染紅a[l]–,a[r+1]++
- 把差分問題轉爲建圖,a[l]++,a[r+1]–變爲從l到r+1的有向邊,同理染紅相反
- 問題可以轉換爲如何使得每個點入度和出度相差<=1
- 如果把所有奇度邊相連那麼只要跑歐拉回路就可以構造出來了,問題就轉化爲板子題了
- 注意離散
代碼:
#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;
}