题意:
1480 打广告
1.0 秒 131,072.0 KB 80 分 5级题
输入
单组测试数据。
第一行有两个整数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
思路:
(1)首先,明确题意,要从n个广告里面选择1个,在m个电视台上选择一个播放这个广告,问影响系数最大是多少??
(2)二分 + 线段树
代码实现:
//线段树求区间交
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 5;
struct Node{
int l;
int r;
}node[maxn];
Node G[maxn];
int cnt = 0;
ll seg[maxn << 2];
bool cmp(Node a,Node b){//排序,去除包含关系
if(a.l != b.l) return a.l < b.l;
else return a.r > b.r;
}
void push_up(int k){
seg[k] = max(seg[k << 1],seg[k << 1|1]);
//为什么要取较大的值??
//线段树的每个节点代表的也是一个区间
//取得的最大值代表一段连续的区间中长度最长的区间长度是多少
}
ll operator&(Node a,Node b){
if(a.l <= b.l&&a.r >= b.r) return b.r - b.l;
if(a.l >= b.l&&a.r <= b.r) return a.r - a.l;
return max(min(a.r,b.r)-max(a.l,b.l),0);
}
void build(int k,int l,int r){//建立线段树
if(l == r){
seg[k] = G[l].l - G[l].r;
return ;
}
int mid = (l + r) >> 1;
build(k << 1,l,mid);
build(k << 1|1,mid + 1,r);
push_up(k);
}
ll query(int k,int l,int r,int L,int R){
//查询?? 查询包含在L到R区间中最长的区间长度
if(L <= l&&R >= r){
return seg[k];
}
int mid = (l + r) >> 1;
if(R <= mid) return query(k<<1,l,mid,L,R);
else if(L > mid) return query(k<<1|1,mid+1,r,L,R);
else return max(query(k<<1,l,mid,L,R),query(k<<1|1,mid+1,r,L,R));
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++){//输入左右区间
scanf("%d%d",&node[i].l,&node[i].r);
}
sort(node + 1,node + 1 + n,cmp);
int now = 1;
G[++cnt] = node[now];
for(int i = 1;i <= n;i++){//去掉包含关系
if(node[i].r > node[now].r){
G[++cnt] = node[i];
now = i;
}
}
build(1,1,cnt);//建立线段树
int a,b,c;
ll ans = 0;
for(int i = 1;i <= m;i++){
scanf("%d%d%d",&a,&b,&c);
int l = 1,r = cnt + 1,mid,L,R;
while(l < r){
mid = (l + r) >> 1;
if(l == mid) break;
if(G[mid].l < a){
l = mid;
}
else r = mid;
}
ans = max(ans,((Node){a,b}&G[l])*c);//区间交集的长度*c
L = l + 1; l = 1; r = cnt + 1;
while(l < r){
mid = (l + r) >> 1;
if(l == mid) break;
if(G[mid].r > b){
r = mid;
}
else l = mid;
}
ans = max(ans,((Node){a,b}&G[r])*c);//答案怎么求??
R = r - 1;
if(R >= L){
ans = max(ans,query(1,1,cnt,L,R)*c);
}
}
printf("%lld\n",ans);
return 0;
}