题意:给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;
}