zoukankan      html  css  js  c++  java
  • UVA 12663 第九届省赛 高桥与低桥 线段树

    题意很简单,n个桥的高度是事先给出来的,然后有m次涨水与落水的高度,问有多少座桥在这m次涨落之后 被淹超过了k次,如果某桥本身被水淹了,此时再涨水,就不能算多淹一次

    看下数据10的五次方,10的五次方的硬循环是避免不了了,很明显在计算被淹次数的时候要能缩到logN的复杂度才好。

    于是想到先对桥由低到高排一下序,然后获取前一次的落水值和这次的涨水值,只要桥高度在涨落直接的必定是又被淹了一次。要多次对序列的某个区间进行加操作,自然是线段树了,确定区间的时候,就用二分,在进行线段树的时候 用懒惰标记

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define Lson (rt<<1),l,mid
    #define Rson (rt<<1|1),mid+1,r
    #define N 100010
    using namespace std;
    int n,m,k;
    int d[N*3],maxk[N*3],flag[N*3],A[N];
    void up(int rt)
    {
        d[rt]=d[rt<<1]+d[rt<<1|1];
        maxk[rt]=maxk[rt<<1]+maxk[rt<<1|1];
    }
    void pushdown(int rt,int l,int r)
    {
        if (l>=r || flag[rt]==0) return;
        int ll=rt<<1;
        int rr=rt<<1|1;
        int mid=(l+r)>>1;
        d[ll]+=flag[rt];
        d[rr]+=flag[rt];
        flag[ll]+=flag[rt];
        flag[rr]+=flag[rt];
        flag[rt]=0;
        if (mid-l+1==1 && d[ll]>=k)
            maxk[ll]=1;
        if (r-mid==1 && d[rr]>=k)
            maxk[rr]=1;
       // up(rt);
    }
    void add(int rt,int l,int r,int L,int R)
    {
        if (L<=l && r<=R)
        {
            pushdown(rt,l,r);
            d[rt]+=r-l+1;
            if (l>=r && d[rt]>=k)
                maxk[rt]=1;
            flag[rt]++;
            return;
        }
        pushdown(rt,l,r);
        int mid=(l+r)>>1;
        if (L<=mid)
            add(Lson,L,R);
        if (R>mid)
            add(Rson,L,R);
        up(rt);
    }
    void incase(int rt,int l,int r)
    {
        if (l>=r)
        {
            if(d[rt]>=k)
                maxk[rt]=1;
            return;
        }
        pushdown(rt,l,r);
        int mid=(l+r)>>1;
        incase(Lson);
        incase(Rson);
        up(rt);
    }
    void build(int rt,int l,int r)
    {
        flag[rt]=0;
        if(l>=r)
        {
            d[rt]=0;
            maxk[rt]=0;
            flag[rt]=0;
            return;
        }
        int mid=(l+r)>>1;
        build(Lson);
        build(Rson);
        up(rt);
    }
    int main()
    {
        int kase=0,a,b,cur;
        while (scanf("%d%d%d",&n,&m,&k)!=EOF)
        {
            for (int i=1;i<=n;i++){
                scanf("%d",&A[i]);
            }
            sort(A+1,A+1+n);
            build(1,1,n);
            cur=1;
            for (int i=1;i<=m;i++)
            {
                scanf("%d%d",&a,&b);
                int l=upper_bound(A+1,A+1+n,cur)-A;
                int r=upper_bound(A+1,A+1+n,a)-A;
                r--;
                if (l<=r)
                add(1,1,n,l,r);
                cur=b;
            }
            incase(1,1,n);
            printf("Case %d: %d
    ",++kase,maxk[1]);
        }
        return 0;
    }

    好久没写线段树了,这个题一写完就WA了,后来发现,首先二分出来的区间先要判断下来,若区间不存在就不要进行插入了,还有就是pushdown,我一开始是计划每次只增加1

    ,要进行下一次懒惰标记的时候先把上一次 的懒惰标记down下去,结果在pushdown函数里面没判断儿子的标记,如果儿子标记了 也得先down儿子啊。结果这样超时了,还是不能这样,索性就每次懒惰标记直接++,最后把整个标记down下去就行

    发现其实d数组完全没有必要的,这个值没有必要维护,只是一开始写的时候没计划的太清,就这样写了。其实没必要。

    最后为了避免某个懒惰标记未被down下去,最后还用个incase函数再走一遍线段树,把值给更新一下。

  • 相关阅读:
    Spring Cloud是什么
    IDEA中常用的10款插件
    Spring Boot自动配置原理分析
    Spring Security自定义授权管理
    Docker常用命令
    pycharm设置开启时不直接打开最后关闭的项目
    django.db.migrations.exceptions.NodeNotFoundError: Migration users.0001_initial dependencies reference nonexistent parent node ('auth', '0009_auto_20200720_0228')
    使用anaconda创建虚拟环境
    windows安装rabbitmq
    docker安装并配置RabbitMQ
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3596760.html
Copyright © 2011-2022 走看看