有n个广告,从1到n编号,他们要求被播出的时间区间是 [li, ri] (可以只播一部分时间,但是区间一定要在这个里面)。
现在有m个电视频道,从1到m编号,每个频道也相应的播出时间区间 [aj, bj] ,还有该时间段观看的人数 ci 。
现在就要选一个广告在某个电视台播出,假如播放的时间区间是 [x, y] ,选择的广告资源是i号,电视频道是j号,那么 [x, y] 一定要同时属于 [li, ri] 和 [aj, bj] 。
选好这三个东西后,开始进行播放,那么就会有一个影响系数,是这么计算的 (y−x)⋅cj
现在要进行恰当的选择,使得这个影响系数最大。
样例解释:可以在第1个电视频道中打第2个广告,时间区间定为 [2, 4] ,那么影响系数就是 (4 − 2)⋅2 = 4 。单组测试数据。 第一行有两个整数n 和 m (1 ≤ n, m ≤ 2*10^5),表示广告数目和电视频道的数目。 接下来n行,每行两个整数 li, ri (0≤ li ≤ ri ≤ 10^9) ,表示每个广告的区间。 接下来m行,每行三个整数 aj, bj, cj (0 ≤ aj ≤ bj ≤ 10^9, 1 ≤ cj ≤ 10^9)。
输出一个最大值,如果不能找到一个有效的方案,输出0。
2 3 7 9 1 4 2 8 2 0 4 1 8 9 3
4
题解:真的是有点神,由于英文不好,cf上的题解看不太明白。
大致思路就是把广告区间按左端点从小到大,右端点从大到小排序,再把被包含的广告区间删去(因为选这个被包含的肯定不如选包含它的广告好),然后把剩下的广告按位置插入线段树,价值为bi-ai,维护区间最大值。
接下来是判断选哪些广告。
枚举每一个电视频道。首先,被该电视频道完全包含的点就可以从线段树中取出最大值,确定这些点可用二分即可。
对于只包含一部分的,我们显然最优的是选择完全包含的那些点的左边第一个或者右边第一个(因为假设你选左边第二个,此时它的ri小于左边第一个(因为不包含嘛,否则这个点的li小于等于左边第一个,ri大于等于左边第一个,左边第一个点就被包含了,这与我们之前的操作相悖),所以我们不如选左边第一个,此时它的ri更大,与电视频道重叠的一段肯定也更大(因为li是小于电视频道的左端点的嘛,所以ri越大,重叠的也就越多喽)),对于右边第一个点也是同理。
所以在这三者中取最大值即可,该值就是这个电视频道的最大影响系数。
最后对所有电视频道的最大影响系数取个max即可。
代码(copy我校dalao):
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,ma[2000000],d,x,y,z,ans;
struct lsg{int x,y;}a[1000000];
void build(int l,int r,int d){
if (l==r){ma[d]=a[l].y-a[l].x;return;}
int m=(l+r)/2;build(l,m,d*2);build(m+1,r,d*2+1);
ma[d]=max(ma[d*2],ma[d*2+1]);
}int findit(int x,int y,int l,int r,int d){
if (x<=l&&y>=r)return ma[d];int m=(l+r)/2,ans=0;
if (x<=m)ans=max(ans,findit(x,y,l,m,d*2));
if (y>m)ans=max(ans,findit(x,y,m+1,r,d*2+1));
return ans;
}int doit(int x,int y){
if (x>a[d].y||y<a[1].x)return 0;
int l=1,r=d,xx,yy,dd=0;
while (l<r){
int m=(l+r)/2;if (a[m].x>x)r=m;else l=m+1;
}
if (x>a[d].x)xx=d+1;else xx=l;
l=1;r=d;
while (l<r){
int m=(l+r+1)/2;if (a[m].y<y)l=m;else r=m-1;
}
if (y<a[1].y)yy=0;else yy=l;
if (xx<=yy)dd=findit(xx,yy,1,d,1);
if (xx-1>0)dd=max(dd,min(y,a[xx-1].y)-max(x,a[xx-1].x));
if (yy+1<=d)dd=max(dd,min(y,a[yy+1].y)-max(x,a[yy+1].x));
return dd;
}bool pd(lsg x,lsg y){return x.x<y.x||x.x==y.x&&x.y>y.y;}
signed main(){
ios::sync_with_stdio(false);
cin>>n>>m;for (int i=1;i<=n;i++)cin>>a[i].x>>a[i].y;
sort(a+1,a+1+n,pd);
d=1;for (int i=2;i<=n;i++)if (a[i].y>a[d].y)a[++d]=a[i];
build(1,d,1);for (int i=1;i<=m;i++){
cin>>x>>y>>z;ans=max(ans,doit(x,y)*z);
}cout<<ans<<endl;
}