任务量统计
工作日五道题(3/5)。
题目链接

https://vjudge.net/problem/UVA-1492
http://acm.hdu.edu.cn/showproblem.php?pid=4052
比网上的线段树不知道快到哪里的平衡树做法
百度了这题的题解,发现都是线段树,就是先把矩形边界延长一下然后求矩形面积的并
由于我不会矩形面积求并,所以想到了下面的做法:
搞一个
s
e
t
set
set,维护这一行的区间
每次插入一个区间,就查询一下前驱后继,维护下当前答案
C++11码风的代码
#include <bits/stdc++.h>
#define maxn 50010
using namespace std;
typedef long long ll;
ll W, H, N, M;
set< pair<ll,ll> > s;
struct machine
{
ll left, right, up, down;
}mch[maxn];
struct event
{
ll l, r, type, id;
}evt[maxn<<1];
bool operator<(event e1, event e2)
{
if(e1.id==e2.id)return e1.type<e2.type;
return e1.id < e2.id;
}
ll read(ll x=0)
{
ll c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
ll f(ll x){return max(0ll,x-M+1);}
int main()
{
ll i, j, tot, ans, now;
while(~scanf("%lld%lld%lld%lld",&W,&H,&N,&M))
{
if(N==0)
{
ans=f(W)*H + f(H)*W;
if(M==1)ans/=2;
printf("%lld\n",ans);
continue;
}
ans=0;
for(i=1;i<=N;i++)
{
mch[i].left=read();
mch[i].up=read();
mch[i].right=read();
mch[i].down=read();
}
tot=0;
for(i=1;i<=N;i++)
{
evt[++tot]=(event){mch[i].left,mch[i].right,+1,mch[i].up};
evt[++tot]=(event){mch[i].left,mch[i].right,-1,mch[i].down+1};
}
sort(evt+1,evt+tot+1);
s.clear();
s.emplace(make_pair(0,0));
s.emplace(make_pair(W+1,W+1));
now=f(W);
for(i=1;i<=tot;i++)
{
if(i==1)ans+=f(W)*(evt[i].id-1);
else ans+=(evt[i].id-evt[i-1].id)*now;
if(i==tot)ans+=f(W)*(H-evt[i].id+1);
if(evt[i].type==+1)
{
auto I=make_pair(evt[i].l,evt[i].r);
s.emplace(I);
auto pre=s.find(I), suf=s.find(I);
pre--, suf++;
now -= f(suf->first - pre->second - 1);
now += f(I.first - pre->second - 1);
now += f(suf->first - I.second - 1);
}
else
{
auto I=make_pair(evt[i].l,evt[i].r);
auto pre=s.find(I), suf=s.find(I);
pre--, suf++;
now -= f(I.first - pre->second - 1);
now -= f(suf->first - I.second - 1);
now += f(suf->first - pre->second - 1);
s.erase(I);
}
}
tot=0;
for(i=1;i<=N;i++)
{
evt[++tot]=(event){mch[i].up,mch[i].down,+1,mch[i].left};
evt[++tot]=(event){mch[i].up,mch[i].down,-1,mch[i].right+1};
}
sort(evt+1,evt+tot+1);
s.clear();
s.emplace(make_pair(0,0));
s.emplace(make_pair(H+1,H+1));
now=f(H);
for(i=1;i<=tot;i++)
{
if(i==1)ans+=f(H)*(evt[i].id-1);
else ans+=(evt[i].id-evt[i-1].id)*now;
if(i==tot)ans+=f(H)*(W-evt[i].id+1);
if(evt[i].type==+1)
{
auto I=make_pair(evt[i].l,evt[i].r);
s.emplace(I);
auto pre=s.find(I), suf=s.find(I);
pre--, suf++;
now -= f(suf->first - pre->second - 1);
now += f(I.first - pre->second - 1);
now += f(suf->first - I.second - 1);
}
else
{
auto I=make_pair(evt[i].l,evt[i].r);
auto pre=s.find(I), suf=s.find(I);
pre--, suf++;
now -= f(I.first - pre->second - 1);
now -= f(suf->first - I.second - 1);
now += f(suf->first - pre->second - 1);
s.erase(I);
}
}
if(M==1)ans/=2;
printf("%lld\n",ans);
}
return 0;
}
博客记录了工作日的做题任务量,给出了题目链接。针对网上用线段树求矩形面积并的题解,博主因不会该方法,提出用平衡树做法,通过set维护区间,插入区间时查询前驱后继来维护答案,还提及是C++11码风的代码。

被折叠的 条评论
为什么被折叠?



