题目链接
https://nanti.jisuanke.com/t/31459
题意
题
意
就
是
按
顺
序
给
出
一
些
左
下
角
在
原
点
的
与
坐
标
轴
平
行
的
矩
形
,
题意就是按顺序给出一些左下角在原点的与坐标轴平行的矩形,
题意就是按顺序给出一些左下角在原点的与坐标轴平行的矩形,
后
来
的
矩
形
会
覆
盖
掉
原
来
矩
形
的
边
,
求
最
后
所
有
能
看
见
的
边
的
总
长
度
。
后来的矩形会覆盖掉原来矩形的边,求最后所有能看见的边的总长度。
后来的矩形会覆盖掉原来矩形的边,求最后所有能看见的边的总长度。
*做法
正
向
做
应
该
很
难
想
,
我
们
考
虑
最
后
一
个
添
加
的
矩
形
一
定
是
完
整
的
,
正向做应该很难想,我们考虑最后一个添加的矩形一定是完整的,
正向做应该很难想,我们考虑最后一个添加的矩形一定是完整的,
而
对
于
之
后
的
矩
形
我
们
只
要
把
两
条
边
分
开
考
虑
,
而对于之后的矩形我们只要把两条边分开考虑,
而对于之后的矩形我们只要把两条边分开考虑,
与
x
轴
平
行
的
边
对
答
案
能
做
的
贡
献
为
x
i
−
他
所
在
的
y
的
最
大
的
x
与x轴平行的边对答案能做的贡献为xi-他所在的y的最大的x
与x轴平行的边对答案能做的贡献为xi−他所在的y的最大的x
与
y
轴
平
行
的
边
对
答
案
能
做
的
贡
献
为
y
i
−
他
所
在
的
x
的
最
大
的
y
与y轴平行的边对答案能做的贡献为yi-他所在的x的最大的y
与y轴平行的边对答案能做的贡献为yi−他所在的x的最大的y
我
们
对
x
,
y
分
别
离
散
化
建
立
权
值
线
段
树
我们对x,y分别离散化建立权值线段树
我们对x,y分别离散化建立权值线段树
每
次
先
查
询
每
条
边
所
能
做
的
贡
献
每次先查询每条边所能做的贡献
每次先查询每条边所能做的贡献
更
新
0
−
x
i
之
间
的
y
的
m
a
x
,
更
新
0
−
y
i
之
间
的
x
的
m
a
x
更新0-xi之间的y的max,更新0-yi之间的x的max
更新0−xi之间的y的max,更新0−yi之间的x的max
单
点
查
询
区
间
更
新
,
用
L
a
z
y
就
可
以
做
到
O
(
n
l
o
g
n
)
单点查询区间更新,用Lazy就可以做到O(nlogn)
单点查询区间更新,用Lazy就可以做到O(nlogn)
代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define dbg(x) cout<<#x<<" = "<<x<<endl
const int maxn = 1e5+10;
int x[maxn],y[maxn];
int Hash_x[maxn],Hash_y[maxn];
int getid(int a[],int n,int x)
{
return lower_bound(a+1,a+1+n,x)-a;
}
struct T
{
int l,r,mid,val;
int add;
}tree_x[maxn<<2],tree_y[maxn<<2];
void push_up(T tree[],int rt)
{
tree[rt].val=max(tree[rt<<1].val,tree[rt<<1|1].val);
}
void push_down(T tree[],int rt)
{
if(tree[rt].add)
{
tree[rt<<1].add=max(tree[rt<<1].add,tree[rt].add);
tree[rt<<1].val=max(tree[rt<<1].val,tree[rt].add);
tree[rt<<1|1].add=max(tree[rt<<1|1].add,tree[rt].add);
tree[rt<<1|1].val=max(tree[rt<<1|1].val,tree[rt].add);
tree[rt].add=0;
}
}
void build(T tree[],int rt,int l,int r)
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].add=0;
if(l==r) return ;
int mid=tree[rt].mid=l+r>>1;
build(tree,rt<<1,l,mid);
build(tree,rt<<1|1,mid+1,r);
push_up(tree,rt);
}
void update(T tree[],int rt,int l,int r,int val)
{
if(r<tree[rt].l||l>tree[rt].r) return ;
if(l<=tree[rt].l&&tree[rt].r<=r)
{
tree[rt].add=max(tree[rt].add,val);
tree[rt].val=max(tree[rt].val,val);
return ;
}
push_down(tree,rt);
if(l<=tree[rt].mid) update(tree,rt<<1,l,r,val);
if(r>tree[rt].mid) update(tree,rt<<1|1,l,r,val);
push_up(tree,rt);
}
int query(T tree[],int rt,int pos)
{
if(tree[rt].l==tree[rt].r) return tree[rt].val;
push_down(tree,rt);
long long ans;
if(pos<=tree[rt].mid) ans=query(tree,rt<<1,pos);
else ans=query(tree,rt<<1|1,pos);
push_up(tree,rt);
return ans;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
for(int i=1;i<=n;i++)
{
Hash_x[i]=x[i];
Hash_y[i]=y[i];
}
sort(Hash_x+1,Hash_x+1+n);
sort(Hash_y+1,Hash_y+1+n);
int d_x=unique(Hash_x+1,Hash_x+1+n)-Hash_x-1;
int d_y=unique(Hash_y+1,Hash_y+1+n)-Hash_y-1;
build(tree_x,1,1,d_x);
build(tree_y,1,1,d_y);
long long ans=0;
for(int i=n;i>=1;i--)
{
int posx=getid(Hash_x,d_x,x[i]);
int posy=getid(Hash_y,d_y,y[i]);
int tmp=query(tree_x,1,posx);
if(tmp<y[i]) ans+=y[i]-tmp;
tmp=query(tree_y,1,posy);
if(tmp<x[i]) ans+=x[i]-tmp;
update(tree_x,1,1,posx,y[i]);
update(tree_y,1,1,posy,x[i]);
}
printf("%lld\n",ans);
return 0;
}