zoukankan      html  css  js  c++  java
  • Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)

    链接:http://codeforces.com/contest/484/problem/E

    题意: 

    给你n个数的,每个数代表高度;

    再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值;

    思路:

    因为查询的到的值一定是输入的其中一个,那么我们可以二分答案,判断二分得到的答案是否符合,那么在这里我们就只需要找到某个数x,查询区间[l,r]有多少个连续的数大于x,这个操作只需要将高度从小到达排序,倒着插入主席树中,值设为1,那么只要维护有多少个连续的1(线段树区间合并的方法),就代表有多少个大于x的连续的数,如果查询到的数大于w,那么就查更大的数并更新答案,如果小于w的话,就找更小的数。

    之前写过倒着插入的主席树,二分答案的线段树,这次合在一起了。。。。

    实现代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 1e5+10;
    int sum[M*40],lsum[M*40],rsum[M*40],ls[M*40],rs[M*40],root[M];
    int idx;
    struct node{
        int x,id;
        bool operator < (const node k) const{
             if(x == k.x) return id < k.id;
             return x < k.x;
        }
    }a[M];
    
    void pushup(int l,int r,int rt){
        lsum[rt] = lsum[ls[rt]];
        rsum[rt] = rsum[rs[rt]];
        int m = (l + r) >> 1;
        if(lsum[rt] == m-l+1) lsum[rt] += lsum[rs[rt]];
        if(rsum[rt] == r - m) rsum[rt] += rsum[ls[rt]];
        sum[rt] = max(lsum[rs[rt]]+rsum[ls[rt]],max(sum[ls[rt]],sum[rs[rt]]));
    }
    
    void update(int old,int &rt,int p,int c,int l,int r){
        rt = ++idx; ls[rt] = ls[old]; rs[rt] = rs[old];
        sum[rt] = sum[old];
        if(l == r) {
            lsum[rt] = sum[rt] = rsum[rt] = c;
            return ;
        }
        int m = (l + r) >> 1;
        if(p <= m) update(ls[old],ls[rt],p,c,l,m);
        else update(rs[old],rs[rt],p,c,m+1,r);
        pushup(l,r,rt);
    }
    
    int query(int L,int R,int l,int r,int rt){
        if(L > R) return 0;
        if(L == l&&R == r) return sum[rt];
        int ret = 0;
        int m = (l + r) >> 1;
        if(R <= m) ret = query(L,R,l,m,ls[rt]);
        else if(L > m) ret = query(L,R,m+1,r,rs[rt]);
        else{
            ret = max(query(L,m,l,m,ls[rt]),query(m+1,R,m+1,r,rs[rt]));
            int lx = min(rsum[ls[rt]],m-L+1);
            int rx = min(lsum[rs[rt]],R - m);
            ret = max(ret,lx+rx);
        }
        return ret;
    }
    
    
    int main()
    {
        int n,q,x,y,w;
        scanf("%d",&n);
        idx = 0; root[n+1] = 0;
        for(int i = 1;i <= n;i ++)  scanf("%d",&a[i].x),a[i].id = i;
        sort(a+1,a+1+n);
        for(int i = n;i >= 1;i --)  update(root[i+1],root[i],a[i].id,1,1,n);
        scanf("%d",&q);
        for(int i = 1;i <= q;i ++){
            scanf("%d%d%d",&x,&y,&w);
            int l = 1,r = n,ans = n;
            while(l <= r){
                int m = (l + r) >> 1;
                int num = query(x,y,1,n,root[m]);
                if(num >= w) l = m+1,ans = m;
                else r = m - 1;
            }
            printf("%d
    ",a[ans].x);
        }
        return 0;
    }
  • 相关阅读:
    (拿来主义) SpringCloud | 第四篇: 断路器(Hystrix)
    (拿来主义) SpringCloud | 第三篇: 服务消费者(Feign)
    (拿来主义) SpringCloud | 第二篇: 服务消费者(rest+ribbon)
    (拿来主义) SpringCloud | 第一篇: 服务的注册与发现(Eureka)
    (拿来主义-10) Spring Boot中使用Swagger2构建强大的RESTful API文档(五)
    (拿来主义-9) Spring Boot构建RESTful API与单元测试(四)
    (拿来主义-8) Spring Boot属性配置文件详解(三)
    (拿来主义-7) Spring Boot工程结构推荐(二)
    springMVC配置文件路径问题
    实现可用的插件系统
  • 原文地址:https://www.cnblogs.com/kls123/p/9607228.html
Copyright © 2011-2022 走看看