zoukankan      html  css  js  c++  java
  • hdu6888(区间取max,维护连续最小值段数)

    题: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
    ",2ll*t1.tr[1].val1+t1.tr[1].val2);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    MAVEN学习-第一个Maven项目的构建
    MAVEN学习笔记-maven的获取和安装
    Hibernate中的锁机制
    java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(2)
    java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(1)
    java中的文件读取和文件写出:如何从一个文件中获取内容以及如何向一个文件中写入内容
    开篇:勇敢踏上这第一步
    有关嵌入式linux的注意点总结
    《nodejs开发指南》微博实例express4.x版
    JavaScript中的数据类型转换
  • 原文地址:https://www.cnblogs.com/starve/p/13715555.html
Copyright © 2011-2022 走看看