CF1781E题解
honglan0301 · · 题解
感谢这道 "trash problem" 把我送到了 rank 200-。
题目分析
不难猜到最优解一定就是最初矩形的并集,那么我们尝试来构造。
我们考虑先将矩形按左端点从小到大排序,并用两个单调队列来记录上下两行中被前面矩形所覆盖住的范围。接下来我们来分类讨论如何处理当前矩形。
1.当前矩形被之前的矩形所完全覆盖。如下图所示(以下蓝色矩形均表示当前矩形,黑色矩形表示之前的矩形)这时显然直接把它删掉就行了。
2.当前矩形仅有一行未被完全覆盖。如下图所示,此时把它更改为未被覆盖的部分并加入该行的单调队列。
3.当前矩形在两行中都未被完全覆盖。如下图所示,此时把单调队列内的所有矩形的右边界置于当前矩形左边界的左侧(若不合法则删掉),并清空单调队列,仅加入当前矩形即可。当前矩形的范围不需更改。
容易发现有且仅有以上三种情况,故可以通过本题。
代码
赛时代码。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
using namespace std;
#define int long long
int t,n,u,v,w,s,b[400005],m;
deque <int> Q[3];
struct jx
{
int l,r,u,d,bh;
}jx[200005];
bool cmp(struct jx x,struct jx y)
{
return x.l!=y.l?x.l<y.l:x.r>y.r;
}
bool cmp2(struct jx x,struct jx y)
{
return x.bh<y.bh;
}
signed main()
{
cin>>t;
while(t--)
{
cin>>n; while(!Q[1].empty()) Q[1].pop_back(); while(!Q[2].empty()) Q[2].pop_back();
for(int i=1;i<=n;i++)
{
cin>>jx[i].u>>jx[i].l>>jx[i].d>>jx[i].r; jx[i].bh=i;
}
sort(jx+1,jx+n+1,cmp);
for(int i=1;i<=n;i++)
{
int nowl=jx[i].l;
while(!Q[1].empty()&&jx[Q[1].back()].r<nowl) Q[1].pop_back();
while(!Q[2].empty()&&jx[Q[2].back()].r<nowl) Q[2].pop_back();
if(jx[i].u==jx[i].d)
{
if(!Q[jx[i].u].empty()&&jx[i].r<=jx[Q[jx[i].u].front()].r)
{
jx[i].l=jx[i].r=jx[i].u=jx[i].d=0;
}
else
{
if(!Q[jx[i].u].empty()) jx[i].l=jx[Q[jx[i].u].front()].r+1;
Q[jx[i].u].push_front(i);
}
}
else
{
if(!Q[1].empty()&&!Q[2].empty()&&jx[i].r<=jx[Q[1].front()].r&&jx[i].r<=jx[Q[2].front()].r)
{
jx[i].l=jx[i].r=jx[i].u=jx[i].d=0;
}
else if(!Q[1].empty()&&jx[i].r<=jx[Q[1].front()].r)
{
if(!Q[2].empty()) jx[i].l=jx[Q[2].front()].r+1;
jx[i].u=jx[i].d;
Q[2].push_front(i);
}
else if(!Q[2].empty()&&jx[i].r<=jx[Q[2].front()].r)
{
if(!Q[1].empty()) jx[i].l=jx[Q[1].front()].r+1;
jx[i].d=jx[i].u;
Q[1].push_front(i);
}
else
{
while(!Q[1].empty())
{
if(jx[Q[1].front()].l<jx[i].l)
{
jx[Q[1].front()].r=jx[i].l-1;
}
else
{
jx[Q[1].front()].r=jx[Q[1].front()].l=jx[Q[1].front()].u=jx[Q[1].front()].d=0;
}
Q[1].pop_front();
}
while(!Q[2].empty())
{
if(jx[Q[2].front()].l<jx[i].l)
{
jx[Q[2].front()].r=jx[i].l-1;
}
else
{
jx[Q[2].front()].r=jx[Q[2].front()].l=jx[Q[2].front()].u=jx[Q[2].front()].d=0;
}
Q[2].pop_front();
}
Q[1].push_front(i); Q[2].push_front(i);
}
}
}
sort(jx+1,jx+n+1,cmp2);
int ans=0;
for(int i=1;i<=n;i++)
{
if(jx[i].d==0) continue;
ans+=(jx[i].d-jx[i].u+1)*(jx[i].r-jx[i].l+1);
}
cout<<ans<<endl;
for(int i=1;i<=n;i++)
{
cout<<jx[i].u<<" "<<jx[i].l<<" "<<jx[i].d<<" "<<jx[i].r<<endl;
}
}
}
写法好像有点麻烦。