[题解]CF542A Place Your Ad Here
思路
首先因为电视台比广告多一个信息,所以通常来说枚举电视台是更有前途的。
因此枚举每一个电视台,考虑所有广告的贡献。对于一个电视台, 是定值,也就是找到所有广告与电视台所表示区间交得最多的那一个。
假设枚举的电视台控制了 区间,则广告 会有三种方式对 有交:
- 。
- 。
- 。
特别的,在这里我们把 归于第二种或者第三种均可。
对于第二、三种情况太平凡了。定义 表示所有右端点为 的广告最左的左端点的位置; 表示所有左端点为 的广告最右的右端点位置。
第二种情况,因为 我们只关心右端点能最远拓展到哪里,因此查询 区间 的最大值;第三种情况同理,查询 区间 的最小值。
第一种情况比较复杂。由于广告被电视台完全包含,因此我们只需要关心广告能取到的最长的长度。
不妨将电视台右端点从大到小排序,好处是可以每一次将右端点超出区间的广告直接弹出集合。然后发现现在在集合中的广告只有左端点的限制了,直接上线段树即可。
对于二三两种情况,维护最值可以用线段树,也可以用 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 国际」许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】