zoukankan      html  css  js  c++  java
  • 【2017 Multi-University Training Contest

    Link:http://acm.hdu.edu.cn/showproblem.php?pid=6047

    Description

    给你一个数列a和一个数列b;
    只告诉你a的前n项各是什么;
    然后让你求第出a的第n+1..2*n项;
    这里a的第i项等于max(a[j]-j)这里j∈[b[k]..i-1];
    (i>n)
    且,每个b只能用来推一次a.
    让你求出2nn+1ai

    Solution

    一开始的a数组,对于ai也直接减去i就好;
    这样在推的时候,直接取区间的最值就可以了,省去了减去i的麻烦;
    把b数组按从小到大的顺序排;
    然后按顺序从左往右用每个b,推出a[n+1],a[n+2]…a[2*n]即可;
    这里,b越小,推出来的a的值就越大;
    为什么优先用b小的?
    因为在较前面,就推出较大的a值;
    这样减去的下标i,就会比较小;
    这样,我们在推下一个a的时候,之前,肯定都是最大的情况了;
    因为我们每个b都会用来推一次;
    而b..n这一段的a是一定的;
    那么,我们就应该尽量让n+1..i-1这一段的a值更大;
    线段树维护区间最值+单点更新即可;

    NumberOf WA

    0

    Reviw


    Code

    #include <bits/stdc++.h>
    #define int long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    using namespace std;
    
    const int N = (int) 50e4;
    const int INF = 0x3f3f3f3f;
    
    int n,ma[(N<<2) +100],a[N+10],b[N+10];
    
    void build(int l,int r,int rt){
        if (l==r){
            ma[rt] = a[l];
            return;
        }
        int m = (l+r)>>1;
        build(lson),build(rson);
        ma[rt] = max(ma[rt<<1],ma[rt<<1|1]);
    }
    
    int get_max(int L,int R,int l,int r,int rt){
        if (L <= l && r <= R)
            return ma[rt];
        int m = (l+r)>>1;
        int temp1 = -INF,temp2 = -INF;
        if (L <= m)
            temp1 = get_max(L,R,lson);
        if (m < R)
            temp2 = get_max(L,R,rson);
        return max(temp1,temp2);
    }
    
    void up_data(int pos,int num,int l,int r,int rt){
        if (l==r){
            ma[rt] = num;
            return;
        }
        int m = (l+r)>>1;
        if (pos <= m){
            up_data(pos,num,lson);
        }else
            up_data(pos,num,rson);
        ma[rt] = max(ma[rt<<1],ma[rt<<1|1]);
    }
    
    main(){
        //freopen("F:\rush.txt","r",stdin);
        while (~scanf("%lld",&n)){
            for (int i = 1;i <= n;i++){
                scanf("%lld",&a[i]);
                a[i] -= i;
            }
            for (int i = i+1;i <= 2*n;i++) a[i] = -INF;
            for (int i = 1;i <= n;i++)
                scanf("%lld",&b[i]);
            sort(b+1,b+1+n);
            build(1,2*n,1);
            int sum = 0,MOD = (int) 1e9+7;
            for (int i = n+1,j = 1;i <= 2*n;i++,j++){
                int bk = b[j];
                int ai = get_max(bk,i-1,1,2*n,1);
                sum = (sum + ai)%MOD;
                up_data(i,ai-i,1,2*n,1);
                a[i] = ai-i;
            }
            printf("%lld
    ",sum);
        }
        return 0;
    }
  • 相关阅读:
    asyncio异步IO--协程(Coroutine)与任务(Task)详解
    python爬虫实战:利用scrapy,短短50行代码下载整站短视频
    深入理解Git的实现原理
    Upsource 代码审查工具安装及使用
    MAC MAMP集成环境安装 PHP 扩展
    千万数据量数据表分表实践
    设计模式:序言
    设计模式 行为型
    PHP5底层原理之变量
    PHP5底层原理之垃圾回收机制
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626154.html
Copyright © 2011-2022 走看看