[题解]CF542A Place Your Ad Here

思路

首先因为电视台比广告多一个信息,所以通常来说枚举电视台是更有前途的。

因此枚举每一个电视台,考虑所有广告的贡献。对于一个电视台,ci 是定值,也就是找到所有广告与电视台所表示区间交得最多的那一个。

假设枚举的电视台控制了 [L,R] 区间,则广告 [l,r] 会有三种方式对 [L,R] 有交:

  1. LlrR
  2. lLrR
  3. LlRr

特别的,在这里我们把 lLRr 归于第二种或者第三种均可。

对于第二、三种情况太平凡了。定义 Mini 表示所有右端点为 i 的广告最左的左端点的位置;Maxi 表示所有左端点为 i 的广告最右的右端点位置。

第二种情况,因为 lL 我们只关心右端点能最远拓展到哪里,因此查询 [1,L1] 区间 Maxi 的最大值;第三种情况同理,查询 [R+1,n] 区间 Mini 的最小值。

第一种情况比较复杂。由于广告被电视台完全包含,因此我们只需要关心广告能取到的最长的长度。

不妨将电视台右端点从大到小排序,好处是可以每一次将右端点超出区间的广告直接弹出集合。然后发现现在在集合中的广告只有左端点的限制了,直接上线段树即可。

对于二三两种情况,维护最值可以用线段树,也可以用 ST 表但是空间上要精细实现。

代码细节较多。

Code

#include <bits/stdc++.h>
#define re register
#define fst first
#define snd second
#define ll long long
#define chmin(a,b) (a = min(a,b))
#define chmax(a,b) (a = max(a,b))

using namespace std;

typedef pair<int,int> pii;
const int N = 8e5 + 10,inf = 1e9 + 10;
int n,m,lg[N];
ll ans; int id1,id2;
pii arr[N],Min[N],Max[N];
vector<int> pt;
vector<pii> str[N];
set<pii> stl[N];

struct sec{
    int l,r,k,id;
}Q[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 seg{
    #define ls(u) (u << 1)
    #define rs(u) (u << 1 | 1)

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

    inline void calc(int u,int x){
        if (stl[x].empty()) tr[u].Max = {-inf,-inf};
        else{
            pii it = *prev(stl[x].end());
            tr[u].Max = {pt[it.fst - 1] - pt[x - 1],it.snd};
        }
    }

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

    inline void build(int u,int l,int r,int op){
        tr[u] = {l,r,{inf,inf},{-inf,-inf}};
        if (l == r){
            if (!op) calc(u,l);
            else{
                tr[u].Min = Min[l]; tr[u].Max = Max[l];
            }
            return;
        }
        int mid = l + r >> 1;
        build(ls(u),l,mid,op); build(rs(u),mid + 1,r,op);
        pushup(u);
    }

    inline void modify(int u,int x){
        if (tr[u].l == tr[u].r) return calc(u,x);
        int mid = tr[u].l + tr[u].r >> 1;
        if (x <= mid) modify(ls(u),x);
        else modify(rs(u),x);
        pushup(u);
    }

    inline pii querymax(int u,int l,int r){
        if (l <= tr[u].l && tr[u].r <= r) return tr[u].Max;
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid && r > mid) return max(querymax(ls(u),l,r),querymax(rs(u),l,r));
        else if (l <= mid) return querymax(ls(u),l,r);
        else return querymax(rs(u),l,r);
    }

    inline pii querymin(int u,int l,int r){
        if (l <= tr[u].l && tr[u].r <= r) return tr[u].Min;
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid && r > mid) return min(querymin(ls(u),l,r),querymin(rs(u),l,r));
        else if (l <= mid) return querymin(ls(u),l,r);
        else return querymin(rs(u),l,r);
    }

    #undef ls
    #undef rs
}VT,ST;

#define find(x) (lower_bound(pt.begin(),pt.end(),x) - pt.begin() + 1)

inline void del(int x){
    for (auto it:str[x]){
        stl[it.fst].erase({x,it.snd});
        ST.modify(1,it.fst);
    }
}

signed main(){
    n = read(),m = read();
    for (re int i = 1,l,r;i <= n;i++){
        l = read(),r = read();
        arr[i] = {l,r};
        pt.push_back(l); pt.push_back(r);
    }
    for (re int i = 1,l,r,k;i <= m;i++){
        l = read(),r = read(),k = read();
        Q[i] = {l,r,k,i};
        pt.push_back(l); pt.push_back(r);
    }
    sort(pt.begin(),pt.end());
    pt.erase(unique(pt.begin(),pt.end()),pt.end());
    const int sz = pt.size();
    fill(Max + 1,Max + sz + 1,make_pair(-inf,-inf));
    fill(Min + 1,Min + sz + 1,make_pair(inf,inf));
    for (re int i = 2;i <= sz;i++) lg[i] = lg[i >> 1] + 1;
    for (re int i = 1;i <= n;i++) arr[i] = {find(arr[i].fst),find(arr[i].snd)};
    for (re int i = 1;i <= m;i++) Q[i] = {find(Q[i].l),find(Q[i].r),Q[i].k,Q[i].id};
    for (re int i = 1;i <= n;i++){
        stl[arr[i].fst].insert({arr[i].snd,i});
        str[arr[i].snd].push_back({arr[i].fst,i});
        chmax(Max[arr[i].fst],make_pair(arr[i].snd,i));
        chmin(Min[arr[i].snd],make_pair(arr[i].fst,i));
    }
    VT.build(1,1,sz,1); ST.build(1,1,sz,0);
    sort(Q + 1,Q + m + 1,[](const sec &a,const sec &b){
        return a.r > b.r;
    });
    for (re int i = Q[1].r + 1;i <= sz;i++) del(i);
    for (re int i = 1;i <= m;i++){
        pii tmpl = {-inf,-inf},tmpr = {-inf,-inf};
        if (Q[i].l > 1){
            pii L = VT.querymax(1,1,Q[i].l - 1);
            if (L.fst >= Q[i].l){
                chmin(L.fst,Q[i].r);
                int len = pt[L.fst - 1] - pt[Q[i].l - 1];
                tmpl = {len,L.snd};
            }
        }
        if (Q[i].r < sz){
            pii R = VT.querymin(1,Q[i].r + 1,sz);
            if (R.fst <= Q[i].r){
                chmax(R.fst,Q[i].l);
                int len = pt[Q[i].r - 1] - pt[R.fst - 1];
                tmpr = {len,R.snd};
            }
        }
        pii tmp = max({tmpl,tmpr,ST.querymax(1,Q[i].l,Q[i].r)});
        if (tmp.fst > 0){
            ll res = 1ll * tmp.fst * Q[i].k;
            if (ans < res){
                ans = res;
                id1 = tmp.snd; id2 = Q[i].id;
            }
        }
        for (re int j = Q[i + 1].r + 1;j <= Q[i].r;j++) del(j);
    }
    printf("%lld\n",ans);
    if (ans) printf("%d %d",id1,id2);
    return 0;
}

作者:WaterSun

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

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

posted @   WBIKPS  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示