zoukankan      html  css  js  c++  java
  • BZOJ5321 & 洛谷4064 & LOJ2274:[JXOI2017]加法——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5321

    https://www.luogu.org/problemnew/show/P4064

    https://loj.ac/problem/2274

    我觉得我永远都不会做九条题的原因就是我傻……这个方法是看同机房dalao代码懂的方法,十分的快。

    想了很多贪心都错了之后发现我是个傻子。

    ”最小值最大“上二分答案,然后我们就知道了每个结点应该被覆盖多少次。

    然后一个显然的贪心:从左到右扫结点,覆盖显然越少越好,必须覆盖的时候每次覆盖选择最大的区间。

    我们直接对区间排序之后用一个堆维护就行了?

    然后记录每个结点被覆盖的情况,直接差分就行了。

    (我最开始贪心错了就是因为没有考虑前面已经过去的区间仍然可以覆盖后面的点……)

    (突然想到我原贪心改改可能也能过?不过那样代码就奇慢了……)

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int INF=1e9;
    const int N=2e5+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct node{
        int l,r;
    }b[N];
    int n,m,k,w,a[N];
    ll c[N];
    priority_queue<int>q;
    inline bool cmp(node a,node b){
        return a.l==b.l?a.r<b.r:a.l<b.l;
    }
    bool pan(ll p){
        int cnt=0;
        for(int i=1;i<=n;i++)c[i]=0;
        while(!q.empty())q.pop();
        for(int i=1,j=1;i<=n;i++){
            while(j<=m&&b[j].l<=i)q.push(b[j++].r);
            c[i]+=c[i-1];
            while(!q.empty()&&c[i]+a[i]<p&&cnt<k){
                if(q.top()>=i)c[i]+=w,c[q.top()+1]-=w,cnt++;
                q.pop();
            }
            if(c[i]+a[i]<p)return 0;
        }
        return 1;
    }
    int main(){
        int t=read();
        while(t--){
            n=read(),m=read(),k=read(),w=read();
            ll l=INF,r;
            for(int i=1;i<=n;i++)a[i]=read(),l=min(l,(ll)a[i]);
            r=l+(ll)w*k;
            for(int i=1;i<=m;i++)b[i].l=read(),b[i].r=read();
            sort(b+1,b+m+1,cmp);
            while(l<r){
                int mid=(l+r+1)>>1;
                if(pan(mid))l=mid;
                else r=mid-1;
            }
            printf("%d
    ",l);
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    URAL 1018 Binary Apple Tree
    URAL 1029 Ministry
    URAL 1039 Anniversary Party
    URAL 1078 Segments
    Codeforces 918D
    Codeforces 918C
    URAL 1495 One-two, One-two 2
    URAL 1244 Gentlemen
    URAL 1658 Sum of Digits
    URAL 1081 Binary Lexicographic Sequence
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9195600.html
Copyright © 2011-2022 走看看