1 条题解

  • 0
    @ 2025-8-24 23:18:09

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar IC0CI
    Huh

    搬运于2025-08-24 23:18:09,当前版本为作者最后更新于2025-07-02 10:10:35,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题面分析

    题目其实就是:给出 nn 段区间 [l,r][l,r] 每段区间都有一个权值 ss,问在 1n1 \sim n 中哪个点覆盖该点的所有区间中权值最大的三个区间权值和最大,输出这个最大权值和。

    关于具体实现

    可以想到用类似单调队列的逻辑,依次遍历 1n1 \sim n 的每个点,由每段区间的 [l,r][l,r] 决定其入队和出队顺序,维护在队列里的区间的权值。

    容易想到可以用priority_queueset分别维护该队列和队列里权值,在入队和出队的时候顺便在集合加入和删除元素。

    需要注意的是,set不可重,可以用增加一个元素或者使用multiset解决。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    
    int rd() //快读
    
    const int N = 2e5 + 5;
    struct frog
    {
        int l,r,s,id;
        bool operator < (const frog &x) const { return r > x.r; }
    }f[N];
    struct frog2
    {
        int l,r,s,id;
        bool operator < (const frog2 &x) const { return (s == x.s) ? id < x.id : (s > x.s); }
    };
    int T,n;
    
    bool cmp(frog x,frog y){ return x.l < y.l; }
    
    signed main()
    {
        T = rd();
        while(T--)
        {
            n = rd();
            for(int i = 1;i <= n;i++)
            {
                int x = rd(),s = rd();
                f[i] = {max(0,i - x),min(n,i + x),s,i};
            }
            sort(f + 1,f + n + 1,cmp);
            priority_queue<frog> q;
            set<frog2> ans;
            int j = 1;
            int res = 0;
            for(int i = 1;i <= n;i++)
            {
                while(!q.empty() && q.top().r < i)
                {
                    frog x = q.top();
                    ans.erase({x.l,x.r,x.s,x.id});
                    q.pop();
                }
                while(j <= n && f[j].l <= i)
                {
                    q.push(f[j]);
                    ans.insert({f[j].l,f[j].r,f[j].s,f[j].id});
                    j++;
                }
                int k = 1;
                auto it = ans.begin();
                int cur = 0;
                while(k <= 3)
                {
                    if(ans.size() < 3) break;
                    cur += (*it).s;
                    it++;
                    k++;
                }
                res = max(res,cur);
            }
            cout << res << '\n';
        }
        return 0;
    }
    
    • 1

    信息

    ID
    12532
    时间
    3000ms
    内存
    512MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者