如果我們把題目裏的邊連出來以後出現了奇環就一定無解,否則我們對於每個連通塊,先黑白染色,然後把同色的區間求交,合併成一個區間(如果是一個孤立點就加入 \([-\infty,+\infty]\) 作爲這個和孤立點區間對立的區間),把得到的兩個區間放在一個二元組裏.現在相當於有若干個區間二元組 \(([l1,r1],[l2,r2])\),然後要決定二元組裏每個區間的分別染成黑白,要使得存在兩個數 \(n1,n2\),滿足 \(t\le n1+n2\le T\),且 \(n1\) 被所有黑區間包含, \(n2\) 被所有白區間包含
上述限制條件可以改爲:黑白染色後得到黑區間的交爲 \([pl,pr]\),白區間的交爲 \([ql,qr]\),要滿足 \([pl+ql,pr+qr]\) 和 \([t,T]\) 區間有交.可以發現所有二元組裏的區間最大左端點 \(zl\) 一定爲 \(pl\) 或 \(ql\) 中的一個,區間最小右端點 \(zr\) 一定爲 \(pr\) 或 \(qr\) 中的一個,那麼我們找到最大左端點和最小右端點所在二元組,並枚舉最大左端點和最小右端點對應的區間是否同色,那麼這時可以先把這兩個(或一個)二元組的染色情況確定下來,然後去確定其他二元組的染色.後面默認最大左端點對應區間是黑色的
由於我們先確定了全局的最大左端點和最小右端點,那如果把最大左端點對應的交區間和後面的區間求交,那麼只有交區間的右端點會變小,同理最小右端點對應的顏色的交區間只有左端點會變大.現在就從小到大枚舉白色對應交區間的左端點 \(l_0\),這時左端點比當前枚舉值更小的二元組裏的區間都可以被染成白色.再考慮另一個沒確定的右端點(即和最小右端點對應區間不同色的交區間的右端點) \(r_0\) ,因爲這時相當於 \(pl+ql\) 已確定,那麼顯然這個 \(r_0\) 是越大越好.對於其他二元組,如果有一個區間可以染白,那麼另一個區間的右端點就要去限制 \(r_0\) 大小,如果兩個兩個區間都可以被染白,那麼選擇右端點更大的區間去限制那個 \(r_0\) 更優.所以這裏可以用 \(\mathrm{multiset}\) 來維護其他二元組的用來限制 \(r_0\) 的右端點,然後取最小值作爲 \(r_0\).如果所有其他二元組都存在可以染白的區間,那就可以用當前的 \(l_0,r_0\) 和最大左端點 \(zl\) ,最小右端點 \(zr\) 作爲 \([pl,pr],[ql,qr]\),這時滿足限制條件就可以輸出答案
注意 \(l_0\) 要和 還沒染色時的黑色交區間左端點 取 max,\(r_0\) 同理,以及要構造合法的 \(n_1,n_2\)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=2e5+10;
int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
return x*w;
}
int to[N<<1],nt[N<<1],hd[N],tot=1;
void adde(int x,int y)
{
++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
}
int sl,sr,n,m,ra[N][2],a[N][2],tt=1,ff[N],co[N],sq[N],tp,cn[N];
bool an[N];
queue<int> q;
bool cmp(int aa,int bb){return a[aa][0]<a[bb][0];}
multiset<int> sb;
int main()
{
sl=rd(),sr=rd(),n=rd(),m=rd();
for(int i=1;i<=n;++i) ra[i][0]=rd(),ra[i][1]=rd();
a[0][0]=-1,a[0][1]=2e9;
for(int i=1;i<=m;++i) adde(rd(),rd());
for(int i=1;i<=n;++i)
if(!ff[i])
{
++tt,a[tt][0]=a[0][0],a[tt][1]=a[0][1];
++tt,a[tt][0]=a[0][0],a[tt][1]=a[0][1];
ff[i]=tt-1,q.push(i);
while(!q.empty())
{
int x=q.front();
q.pop();
int xt=tt^1^co[x];
a[xt][0]=max(a[xt][0],ra[x][0]),a[xt][1]=min(a[xt][1],ra[x][1]);
for(int j=hd[x];j;j=nt[j])
{
int y=to[j];
if(ff[y])
{
if(co[x]==co[y]){puts("IMPOSSIBLE");return 0;}
}
else ff[y]=ff[x]^1,co[y]=co[x]^1,q.push(y);
}
}
if(a[tt-1][0]>a[tt-1][1]||a[tt][0]>a[tt][1]){puts("IMPOSSIBLE");return 0;}
}
int m1=0,m2=0;
for(int i=2;i<=tt;++i)
{
if(a[i][0]>a[m1][0]) m1=i;
if(a[i][1]<a[m2][1]) m2=i;
}
if(a[m1][0]<=a[m2][1])
{
int z1=a[m1][0],z2=a[m2][1],pl=max(max(a[m1^1][0],a[m2^1][0]),0),pr=min(a[m1^1][1],a[m2^1][1]),rs=(tt>>1)-2+((m1>>1)==(m2>>1));
an[m1>>1]=m1&1,an[m2>>1]=m2&1;
for(int i=2;i<=tt;++i)
if((i>>1)!=(m1>>1)&&(i>>1)!=(m2>>1)) sq[++tp]=i;
sort(sq+1,sq+tp+1,cmp);
sb.insert(pr);
for(int i=0;i<=tp;++i)
{
int x=sq[i];
if(x)
{
if(a[x][0]>pr) break;
++cn[x>>1];
if(cn[x>>1]==1) --rs,sb.insert(a[x][1]),an[x>>1]=(x&1)^1;
else
{
int y=x^1;
if(a[x][1]>a[y][1])
sb.erase(sb.find(a[y][1])),sb.insert(a[x][1]),an[x>>1]^=1;
}
}
int nl=max(pl,a[x][0]),nr=(*sb.begin());
if(rs<=0&&nl<=nr&&max(nl+z1,sl)<=min(nr+z2,sr))
{
puts("POSSIBLE");
int mm=sl-(z1+nl);
if(mm>0)
{
if(z1+mm<=z2) z1+=mm;
else nl+=mm-(z2-z1),z1=z2;
}
printf("%d %d\n",z1,nl);
for(int i=1;i<=n;++i) printf("%d",1+((an[ff[i]>>1]^ff[i])&1));
return 0;
}
}
}
tp=0;
sb.clear();
memset(cn,0,sizeof(cn));
if(m1!=m2)
{
int z1=a[m1][0],z2=a[m2][1],pl=max(max(a[m1^1][0],a[m2][0]),0),pr=min(a[m1][1],a[m2^1][1]),rs=(tt>>1)-2+((m1>>1)==(m2>>1));
an[m1>>1]=m1&1,an[m2>>1]=(m2&1)^1;
for(int i=2;i<=tt;++i)
if((i>>1)!=(m1>>1)&&(i>>1)!=(m2>>1)) sq[++tp]=i;
sort(sq+1,sq+tp+1,cmp);
sb.insert(pr);
for(int i=0;i<=tp;++i)
{
int x=sq[i];
if(x)
{
if(a[x][0]>z2) break;
++cn[x>>1];
if(cn[x>>1]==1) --rs,sb.insert(a[x^1][1]),an[x>>1]=(x&1)^1;
else
{
int y=x^1;
if(a[y][1]>a[x][1])
sb.erase(sb.find(a[x][1])),sb.insert(a[y][1]),an[x>>1]^=1;
}
}
int nl=max(pl,a[x][0]),nr=(*sb.begin());
if(rs<=0&&z1<=nr&&nl<=z2&&max(nl+z1,sl)<=min(nr+z2,sr))
{
puts("POSSIBLE");
int mm=sl-(z1+nl);
if(mm>0)
{
if(z1+mm<=nr) z1+=mm;
else nl+=mm-(nr-z1),z1=nr;
}
printf("%d %d\n",z1,nl);
for(int i=1;i<=n;++i) printf("%d",1+((an[ff[i]>>1]^ff[i])&1));
return 0;
}
}
}
puts("IMPOSSIBLE");
return 0;
}