ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

hdu6888(区间取max,维护连续最小值段数)

2020-09-22 23:33:40  阅读:301  来源: 互联网

标签:int max tr 段数 hdu6888 mi 矩形 root


题:http://acm.hdu.edu.cn/showproblem.php?pid=6888

题意:给定n个二维坐标系上的矩形,问每插入一个矩形后这些矩形的周长并是多少(强制在线,1<=n<=1e5,1<=x,y<=1e9,且每个矩形的下边界一定是x轴)。

分析:

  • 强条件:每个矩形的下边界一定是x轴,那么就可以把矩形的周长并分为俩部分来算:竖线和横线;
  • 对于横线:简单的区间覆盖;
    • 由于使1e9,先离散化,预算出每个线段长度,当要更新时就标记信号要用到之前预处理的线段长度,这部分答案*2,因为有上下边界;
  • 对于竖线:对于每个被覆盖的位置都有一个值a[i],那么答案就是∑|a[ i ] - a[ i - 1] |;
    • 对于每次加进来的一个矩阵,对于竖线部分的影响就是区间取max,这个用jls线段树解决,难点就是在维护jls线段树的同时维护竖线的答案总和;
    • 我们发现,在维护区间max时,我们用到了最小值mi和次小值se,让要更新值v在mi<c<se更新,那么那些mi的位置更新成c对答案的影响就是减去c-mi(若这个位置旁边的值不是mi);
    • 那么就是在维护取max操作的同时维护这样的“断层”(a[ i ]和a[ i - 1 ]中只有一个是区间的mi)的个数cnt;
    • 这个只要知道即将合并的俩个区间的左右端点的a[i]值即可,通过判断左儿子的右断点和右儿子的左端点来使cnt+=0 or 1;
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
#define lc root<<1
#define rc root<<1|1
typedef long long ll;
const int mod=1e9+7;
const int M=1e6+6;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
struct QU{
    int l,r,h;
}q[M];
int tmp[M];
struct JlsSegTree{
    struct node{
        ll mi,se;///最小值和次小值
        ll cnt;///a[i]和a[i+1]之间其中一个是区间mi这样间隔的个数
        ll l,r;///左右端点的值
        ll len;///离散前区间的长度
        ll val1;///区间覆盖
        ll val2;///sum(|a[i]-a[i+1]|)
        int lz;
        node (){
            cnt=l=r=len=val1=val2=mi=se=lz=0;
        }
        void Max(ll v){
            if(mi >= v) return;
            l = max(l,v), r = max(r,v);
            val2 -= cnt * (v-mi);
            mi = v;
        }
    }tr[M<<2];
    void up(int root){
        tr[root].cnt=0;
        tr[root].l=tr[lc].l;
        tr[root].r=tr[rc].r;
        tr[root].val2=tr[lc].val2+tr[rc].val2;
        tr[root].mi=min(tr[lc].mi,tr[rc].mi);
        tr[root].se=min(tr[lc].se,tr[rc].se);
        if(tr[lc].mi!=tr[rc].mi)
            tr[root].se=min(tr[root].se,max(tr[lc].mi,tr[rc].mi));
        if(tr[root].mi==tr[lc].mi) tr[root].cnt+=tr[lc].cnt;
        if(tr[root].mi==tr[rc].mi) tr[root].cnt+=tr[rc].cnt;
        if(tr[lc].r!=tr[rc].l&&(tr[lc].r==tr[root].mi||tr[rc].l==tr[root].mi))///考虑合并的“断层”
            tr[root].cnt++;
        tr[root].val2+=abs(tr[lc].r-tr[rc].l);
    }
    void pushdown(int root){
        tr[lc].Max(tr[root].mi);
        tr[rc].Max(tr[root].mi);
    }
    void build(int root,int l,int r){
        tr[root]=node();
        if(l==r){
            tr[root].se=inf;
            tr[root].len=tmp[l]-tmp[l-1];
            return ;
        }
        int midd=(l+r)>>1;
        build(lson);
        build(rson);
        up(root);
        tr[root].len=tr[lc].len+tr[rc].len;
    }
    void update1(int L,int R,int root,int l,int r){///区间覆盖更新
        if(L<=l&&r<=R){
            tr[root].val1=tr[root].len;
            tr[root].lz=1;
            return ;
        }
        if(tr[root].lz){
            tr[lc].val1=tr[lc].len;
            tr[rc].val1=tr[rc].len;
            tr[lc].lz=tr[rc].lz=1;
            tr[root].lz=0;
        }
        int midd=(l+r)>>1;
        if(L<=midd)
            update1(L,R,lson);
        if(R>midd)
            update1(L,R,rson);
        tr[root].val1=tr[lc].val1+tr[rc].val1;
    }
    void update2(ll v,int L,int R,int root,int l,int r){
        if(tr[root].mi>=v)
            return ;
        if(L<=l&&r<=R&&tr[root].se>v){
            tr[root].Max(v);
            return ;
        }
        int midd=(l+r)>>1;
        pushdown(root);
        if(L<=midd)
            update2(v,L,R,lson);
        if(R>midd)
            update2(v,L,R,rson);
        up(root);
    }
}t1;

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        scanf("%d",&n);
        int tot=0;
        tmp[++tot]=inf;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h);
            tmp[++tot]=q[i].l, tmp[++tot]=q[i].r;
        }
        sort(tmp+1,tmp+1+tot);
        int m=unique(tmp+1,tmp+1+tot)-tmp-1;
        t1.build(1,1,m);
        auto getid = [&](int x){
            return lower_bound(tmp+1,tmp+1+m,x)-tmp;
        };
        for(int i=1;i<=n;i++){
            int posl = getid(q[i].l), posr = getid(q[i].r);
            t1.update1(posl+1,posr,1,1,m);///区间覆盖更新
            t1.update2(q[i].h,posl+1,posr,1,1,m);///a[i]-a[i-1]总和更新
            printf("%lld\n",2ll*t1.tr[1].val1+t1.tr[1].val2);
        }
    }
    return 0;
}
View Code

 

标签:int,max,tr,段数,hdu6888,mi,矩形,root
来源: https://www.cnblogs.com/starve/p/13715555.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有