https://codeforces.com/gym/102055/problem/B
训练的时候队友WA K太久了这题我口胡完了没写完。
补题发现卧槽巨卡空间,stl空间常数巨大,底层都是vector,vector自带3倍空间常数,然后又不知道有其他的什么空间消耗= =
本来用了两个priority_queue套了一堆pair然后mle
然后换成了pair的multiset又mle
最后multiset<int> 过了,我透
首先,限制成环比impossible,可以使用虚点并查集判断,x,y在不同边相当于x 和 y+n ,x+n 和 y 连边,如果x y在某时属于同一个并查集那么必定成环了。
然后去dfs没成环的树,这种type=2,有两种情况,要么选mx[0] mx[1]为最大最小值,要么选mi[0] mx[1]为最大最小值。
如果是单个点就是type=1,要么选 mx[0] 要么选 mi[0]作为他的能力值。
我们先全选最大,这样保证在当前最大值下,最小值也最大,那么对于当前的最大值,最大值-最小值就是当前的答案。
接下来我们考虑到,如果不变化这个最大值,怎么变最小值只会变小,答案不会更优
所以我们考虑减小这个最大值,
如果是tp=1,那么就变成mi[0]
如果是tp=2,那么就变成mi[0],mi[1]
我们要一步一步减小最大值,所以要按照mx[0]从大到小排序。
考虑一下细节,当我们dfs树的时候。得到两组最大值最小值,由于我们一开始在最初情况下想让最小值最大,所以如果mx[1]>mx[1]则交换着两组值。
#include<bits/stdc++.h>
#define maxl 200010
using namespace std;
int n,m,cnt,tot,cas=0,ans;
int f[maxl*2],ehead[maxl];
int mx[2],mi[2];
struct ed
{
int to,nxt;
}e[maxl*2];
struct node
{
int l,d;
}a[maxl];
struct nod
{
int tp;
int mx[2],mi[2];
}b[maxl];
int st[maxl];
bool vis[maxl];
multiset <int> s;
inline int find(int x)
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
inline void add(int u,int v)
{
e[++cnt].to=v;e[cnt].nxt=ehead[u];ehead[u]=cnt;
}
inline void dfs(int u,int k,int fa)
{
vis[u]=true;
if(k==0)
{
mx[0]=max(mx[0],a[u].l);
mx[1]=min(mx[1],a[u].l);
mi[0]=max(mi[0],a[u].d);
mi[1]=min(mi[1],a[u].d);
}
else
{
mx[0]=max(mx[0],a[u].d);
mx[1]=min(mx[1],a[u].d);
mi[0]=max(mi[0],a[u].l);
mi[1]=min(mi[1],a[u].l);
}
int v;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(v==fa || vis[v])
continue;
dfs(v,k^1,u);
}
}
inline void prework()
{
ans=2e9;
scanf("%d%d",&n,&m);
for(int i=1;i<=n*2;i++)
f[i]=i;
for(int i=1;i<=n;i++)
ehead[i]=0,vis[i]=false;
int x,y,xx,yy;
cnt=0;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if(find(x)==find(y))
{
ans=-1;
continue;
}
xx=find(x);yy=find(y+n);
if(f[yy]!=xx)
f[yy]=xx;
xx=find(x+n);yy=find(y);
if(f[yy]!=xx)
f[yy]=xx;
add(x,y);add(y,x);
}
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].l,&a[i].d);
if(ans==-1)
return;
tot=0;
for(int i=1;i<=n;i++)
if(!vis[i])
{
if(ehead[i]==0)
{
vis[i]=true;
++tot;b[tot].tp=1;
b[tot].mx[0]=max(a[i].l,a[i].d);
b[tot].mi[0]=min(a[i].l,a[i].d);
}
else
{
mx[0]=0;mx[1]=2e9;
mi[0]=0;mi[1]=2e9;
dfs(i,0,0);
if(mi[1]>mx[1])
swap(mx[0],mi[0]),swap(mx[1],mi[1]);
++tot;b[tot].tp=2;
b[tot].mx[0]=mx[0];b[tot].mx[1]=mx[1];
b[tot].mi[0]=mi[0];b[tot].mi[1]=mi[1];
}
}
}
inline bool cmp(const nod &x,const nod &y)
{
return x.mx[0]>y.mx[0];
}
inline void mainwork()
{
if(ans==-1)
return;
s.clear();
sort(b+1,b+1+tot,cmp);
for(int i=1;i<=tot;i++)
if(b[i].tp==1)
{
st[i]=1;
s.insert(b[i].mx[0]);
}
else
{
st[i]=1;
s.insert(b[i].mx[0]);
s.insert(b[i].mx[1]);
}
int id;
for(int i=1;i<=tot;i++)
{
ans=min(ans,(*s.rbegin())-(*s.begin()));
if(b[i].tp==1)
{
st[i]=2;
s.erase(s.find(b[i].mx[0]));
s.insert(b[i].mi[0]);
}
else
{
st[i]=2;
s.erase(s.find(b[i].mx[0]));
s.erase(s.find(b[i].mx[1]));
s.insert(b[i].mi[0]);
s.insert(b[i].mi[1]);
}
}
ans=min(ans,(*s.rbegin())-(*s.begin()));
}
inline void print()
{
++cas;
if(ans==-1)
printf("Case %d: IMPOSSIBLE\n",cas);
else
printf("Case %d: %d\n",cas,ans);
}
int main()
{
//freopen("B.in","r",stdin);
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}