题意:
有条1——1e9的坐标轴,给出n给区间l,r,v表示l到r范围内的点价值为v
你可以得到连续的一段区间的价值,区间最长为k,求可以得到的最大值
解析:
相当于在长度固定的情况下移动区间,有以下结论
- 选取区间的端点一定是某个给出的区间的端点,因为如果两端都在某个区间的中间话,往左或往右一定可以做到单调不减
所以,我们可以扫一遍所有区间的端点,使之为我们选取区间的端点
接下来就是实现和优化了
因为是一维坐标轴且需要得出的答案是一段连续区间,所以可以参考尺取法来实现,在左端点往后移动的时候,维护nowans,删去前面段的价值,加进后面段的价值,ans取个max就行
然后以右端点的时候只要转化一下端点值,再套上面的方法做一遍就行
代码:
struct node{
int l,r,v;
bool operator < (const node a)const{
return l<a.l;
}
void init(){
scanf("%d%d%d",&l,&r,&v);
}
}e[100009];
int main(){
int t=read();
while(t--){
int n=read(),k=read();
for(int i=1;i<=n;i++)e[i].init();
sort(e+1,e+1+n);
////////////////以左端点开始
e[0].l=e[1].l-k;//为了移动r
e[0].r=e[1].l-1;
e[0].v=0;
D ans=0,nowans=0;
int r=e[1].l-1,ar=0;//当前的右界为r,且右界在第ar段的前面或里面
for(int i=1;i<=n;i++){
nowans-=(D)(e[i-1].r-e[i-1].l+1)*e[i-1].v;
int tmpr=r+e[i].l-e[i-1].l;
while(1){
if(ar>n)break;
if(tmpr<e[ar].l)break;
if(tmpr>=e[ar].l&&tmpr<=e[ar].r){
nowans+=(D)(tmpr-max(r+1,e[ar].l)+1)*e[ar].v;
break;
}
else{
nowans+=(D)(e[ar].r-max(r+1,e[ar].l)+1)*e[ar].v;
ar++;
}
}
r=tmpr;
ans=max(ans,nowans);
}
////////////////以右端点开始
for(int i=1;i<=n;i++){
e[i].l=1000000000-e[i].l+1;
e[i].r=1000000000-e[i].r+1;
swap(e[i].l,e[i].r);
}
for(int i=1;i<=n/2;i++)swap(e[i],e[n-i+1]);
e[0].l=e[1].l-k;
e[0].r=e[1].l-1;
e[0].v=0;
nowans=0;
r=e[1].l-1,ar=0;
for(int i=1;i<=n;i++){
nowans-=(D)(e[i-1].r-e[i-1].l+1)*e[i-1].v;
int tmpr=r+e[i].l-e[i-1].l;
while(1){
if(ar>n)break;
if(tmpr<e[ar].l)break;
if(tmpr>=e[ar].l&&tmpr<=e[ar].r){
nowans+=(D)(tmpr-max(r+1,e[ar].l)+1)*e[ar].v;
break;
}
else{
nowans+=(D)(e[ar].r-max(r+1,e[ar].l)+1)*e[ar].v;
ar++;
}
}
r=tmpr;
ans=max(ans,nowans);
}
////////
printf("%lld\n",ans);
}
}