ACM-ICPC 2018 徐州赛区网络预赛 G (离散化 + 树状数组 + 区间最大值 + 模拟)

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值