[LOJ2274][JXOI2017] add binary answer + priority queue

Keywords: less

The general idea is: first, bisect the answer x, and check is to scan from left to right. If the current value is less than x, greedily select the rightmost endpoint to add it, and then maintain the interval addition with line tree / tree array, or directly maintain the times of addition with priority queue.
Specifically, open two priority queues Q,H, the former maintains the maximum value of the right end point of the current optional interval, the latter maintains the minimum value of the left end point of the current selected area, and then scans from left to right to i:
1. Add Q to the interval with the left endpoint at i.
2. Discard the left end point less than i from H.
3. The current value of i position should be Ai+sizeH * a, and then if it is less than x, add it with the interval in Q. if q is not enough or the total interval exceeds k, it is illegal.
Time complexity O(nlog2n)
code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define mid (L+R>>1)
#define N 200010
using namespace std;
int n,m,k,d,a[N];
vector<int> r[N];
int read()
{
    int x=0;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    return x;
}
priority_queue<int,vector<int>,greater<int> > H;
priority_queue<int> Q;
bool check(int x)
{
    while(!Q.empty()) Q.pop();
    while(!H.empty()) H.pop();
    int tk=k;
    for(int i=1;i<=n;i++)
    {   
        for(int j=0;j<r[i].size();j++)
            Q.push(r[i][j]);    
        while(!H.empty()&&H.top()<i) H.pop();
        for(int j=a[i]+H.size()*d;j<x;j+=d) 
        {
            if(Q.empty()||tk<=0||Q.top()<i) return 0;
            H.push(Q.top()),Q.pop(),tk--;
        }
    }
    return 1;
}
int main()
{
    int ca=read();
    while(ca--)
    {
        n=read();m=read();k=read();d=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        for(int i=1,x,y;i<=m;i++)
            x=read(),y=read(),r[x].push_back(y);
        int L,R;
        for(L=0,R=1e9;L<R;)
            if(check(mid)) L=mid+1;
            else R=mid;
        printf("%d\n",L-1);
        for(int i=1;i<=n;i++)
            r[i].clear();
    }
    return 0;
}

Posted by PugJr on Sun, 03 May 2020 00:20:12 -0700