[题解]CF377D Developing Game

这是一个不需要扫描线的做法/cy

思路

注意到选择出来的人的 [li,ri] 必须有交,并且每个人的 vi 都得在交里面。

考虑枚举交的左端点 L,维护每一个右端点 R 的答案。容易发现当一个人 i 满足 liLviRri 时会对一个右端点 R 产生贡献。

于是当 liLvi 时,对于所有在 [vi,ri] 区间的 R 都可以被第 i 个人贡献。

一个经典的处理这个问题的方法是,在 L 移动到 li 时将第 i 个人的贡献加入,在 vi+1 时将第 i 个人的贡献减去。容易使用线段树维护,区间加法,全局最值。

Code

#include <bits/stdc++.h>
#define re register
#define fst first
#define snd second

using namespace std;

typedef pair<int,int> pii;
const int N = 3e5 + 10;
int n,ans,ansl,ansr;
vector<pii> Q[N];

struct sec{
    int l,r,v;
}arr[N];

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

struct{
    #define ls(u) (u << 1)
    #define rs(u) (u << 1 | 1)
    #define mid (tr[u].l + tr[u].r >> 1)

    struct node{
        int l,r,tag;
        pii Max;
    }tr[N << 2];

    inline void calc(int u,int k){
        tr[u].Max.fst += k; tr[u].tag += k;
    }

    inline void pushup(int u){
        tr[u].Max = max(tr[ls(u)].Max,tr[rs(u)].Max);
    }

    inline void pushdown(int u){
        if (tr[u].tag){
            calc(ls(u),tr[u].tag); calc(rs(u),tr[u].tag);
            tr[u].tag = 0;
        }
    }

    inline void build(int u,int l,int r){
        tr[u] = {l,r};
        if (l == r) return (tr[u].Max.snd = l),void();
        build(ls(u),l,mid); build(rs(u),mid + 1,r);
        pushup(u);
    }

    inline void modify(int u,int l,int r,int k){
        if (l <= tr[u].l && tr[u].r <= r) return calc(u,k);
        pushdown(u);
        if (l <= mid) modify(ls(u),l,r,k);
        if (r > mid) modify(rs(u),l,r,k);
        pushup(u);
    }

    #undef ls
    #undef rs
    #undef mid
}T;

int main(){
    n = read();
    for (re int i = 1,l,r,v;i <= n;i++){
        l = read(),v = read(),r = read();
        arr[i] = {l,r,v};
        Q[l].push_back({1,i});
        Q[v + 1].push_back({-1,i});
    }
    T.build(1,1,3e5);
    for (re int i = 1;i <= 3e5;i++){
        for (pii p:Q[i]){
            sec tmp = arr[p.snd];
            T.modify(1,tmp.v,tmp.r,p.fst);
        }
        pii res = T.tr[1].Max;
        if (res.fst > ans){
            ans = res.fst;
            ansl = i,ansr = res.snd;
        }
    }
    printf("%d\n",ans);
    for (re int i = 1;i <= n;i++){
        if (arr[i].l <= ansl && ansr <= arr[i].r && ansl <= arr[i].v && arr[i].v <= ansr) printf("%d ",i);
    }
    return 0;
}

作者:WaterSun

出处:https://www.cnblogs.com/WaterSun/p/18666404

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   WBIKPS  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 提示词工程——AI应用必不可少的技术
· 地球OL攻略 —— 某应届生求职总结
· 字符编码:从基础到乱码解决
· SpringCloud带你走进微服务的世界
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示