loj2274 「JXOI2017」加法

Posted poorpool

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj2274 「JXOI2017」加法相关的知识,希望对你有一定的参考价值。

二分一下,然后从左到右扫描,扫到左端点就把区间 push 到堆里。
每次有点不符合二分的值时,就贪心地选择右端点最远的 add。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int T, n, m, k, aa, dui[200005], din, a[200005], sta[200005], cnt, j, c[200005];
int uuu;
struct Node{
    int lll, rrr;
}nd[200005];
bool cmp(Node x, Node y){
    return x.lll<y.lll;
}
int lb(int x){
    return x&-x;
}
void add(int p, int x){
    for(int i=p; i<=n+1; i+=lb(i))
        c[i] += x;
}
int query(int p){
    int re=0;
    for(int i=p; i; i-=lb(i))
        re += c[i];
    return re;
}
bool chk(int lim){
    memset(c, 0, sizeof(c));
    din = cnt = uuu = 0;
    j = 1;
    for(int i=1; i<=n; i++)
        if(a[i]<lim)
            sta[++cnt] = i;
    for(int i=1; i<=cnt; i++){
        while(j<=m && nd[j].lll<=sta[i]){
            dui[++din] = nd[j].rrr;
            push_heap(dui+1, dui+1+din);
            j++;
        }
        while(a[sta[i]]+query(sta[i])<lim){
            uuu++;
            if(uuu>k || !din)   return false;
            add(sta[i], aa);
            add(dui[1]+1, -aa);
            pop_heap(dui+1, dui+1+din);
            din--;
        }
    }
    return true;
}
int main(){
    cin>>T;
    while(T--){
        scanf("%d %d %d %d", &n, &m, &k, &aa);
        for(int i=1; i<=n; i++)
            scanf("%d", &a[i]);
        for(int i=1; i<=m; i++)
            scanf("%d %d", &nd[i].lll, &nd[i].rrr);
        sort(nd+1, nd+1+m, cmp);
        int l=1, r=120000000, mid, re;
        while(l<=r){
            mid = (l + r) >> 1;
            if(chk(mid))    re = mid, l = mid + 1;
            else    r = mid - 1;
        }
        printf("%d\n", re);
    }
    return 0;
}

以上是关于loj2274 「JXOI2017」加法的主要内容,如果未能解决你的问题,请参考以下文章

P4064 [JXOI2017]加法

P4064 [JXOI2017]加法

P4064 [JXOI2017]加法

[JXOI2017]加法

[bzoj5321] [Jxoi2017]加法

JXOI2017 题解