G
题意
按照顺序往坐标系的第一象限放矩形,其中矩形的一个顶点和原点重合。数据中给出矩形右上方顶点的位置 (x,y) ( x , y ) 。已知后放上的矩形会覆盖之前的矩形,问,露出来的边界的总长度是多少(不计坐标轴)(依然是来自于队友的翻译,看看题会比较好理解)
思路
由于题目给出,矩形不会完全覆盖,所以对于任意两个矩形的右上顶点
(xi,yi)
(
x
i
,
y
i
)
和
(xj,yj)
(
x
j
,
y
j
)
,若
xi<xj
x
i
<
x
j
则
yi>yj
y
i
>
y
j
一定成立。
那么我们考虑倒着放矩形,那么他的边长
xi, yi
x
i
,
y
i
会被挡住多少?由于倒着放,那么它的横边会被之前放的所有
xj>xi
x
j
>
x
i
中,
max(xj)
max
(
x
j
)
挡住。
那么我们只需要维护一个区间最大值
Or
O
r
区间最小值 + 单点更新就可以解决这个问题。
赛场上使用的是线段树,赛后用树状数组补了一下,但是维护的是一个
[nowx, maxn)
[
n
o
w
x
,
m
a
x
n
)
的最大值,现在想一想可以正着维护就不用倒着离散化了。
代码
int x[maxn], y[maxn];
PII a[maxn];
set<int> sx, sy;
map<int, int> mpx, mpy;
void add(int *a, int x, int k){
while(x < maxn){
a[x] = max(a[x], k);
x += x&-x;
}
}
int query(int *a, int x){
int ans = 0;
while(x){
ans = max(ans, a[x]);
x -= x&-x;
}
return ans;
}
int main()
{
int n;
ll ans = 0;
sd(n);
rep(i, 0, n) {
sdd(a[i].fi, a[i].se);
sx.insert(a[i].fi);
sy.insert(a[i].se);
}
int cnt = 0;
for(auto p : sx)
mpx[p] = ++cnt;
cnt = 0;
for(auto p : sy)
mpy[p] = ++cnt;
per(i, 0, n) {
int nowx = mpx[a[i].fi], nowy = mpy[a[i].se];
ans += a[i].fi - query(y, nowy) + a[i].se - query(x, nowx);
add(x, nowx, a[i].fi);
add(y, nowy, a[i].se);
}
pld(ans);
return 0;
}

1305

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



