题目链接:https://codeforces.com/contest/1250/problem/C
题意:给定多个区间,以及每个区间对应的价值p;选定一个区间,L,R,能获得的总价值为其所包含的小区间的价值和-k*(R-L+1);求最大总价值。
参考:https://blog.csdn.net/weixin_43851525/article/details/102943189
题解:先把所有的区间都加上,暴力枚举左端点,取最大值。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
const int maxn=200010;
#define ls rt<<1
#define rs rt<<1|1
ll mx[maxn<<2],lazy[maxn<<2];
void pushup(int rt){
mx[rt]=max(mx[ls],mx[rs]);
}
void pushdown(int rt){
lazy[ls]+=lazy[rt];
lazy[rs]+=lazy[rt];
mx[ls]+=lazy[rt];
mx[rs]+=lazy[rt];
lazy[rt]=0;
}
void build(int rt,int l,int r){
lazy[rt]=0;
if(l==r){
mx[rt]=0;//
return;
}
int m=(l+r)>>1;
build(ls,l,m);
build(rs,m+1,r);
pushup(rt);
}
void update(int rt,int l,int r,int a,int b,ll val){
if(l>=a&&r<=b){
mx[rt]+=val;
lazy[rt]+=val;
return;
}
if(lazy[rt]) pushdown(rt);
int m=(l+r)>>1;
if(a<=m) update(ls,l,m,a,b,val);
if(m<b) update(rs,m+1,r,a,b,val);
pushup(rt);
}
int n;
ll k;
struct node{
int l,r,id;
ll p;
}a[maxn];
bool cmp(const node &x,const node &y){
return x.l<y.l;
}
bool cmp2(const node &x,const node &y){
return x.r<y.r;
}
int ans[maxn],tot;
int main()
{
scanf("%d%I64d",&n,&k);
int l,r;
ll p;
int N=0;
for(int i=1;i<=n;i++){
scanf("%d%d%I64d",&l,&r,&p);
a[i].l=l;a[i].r=r;a[i].p=p;
a[i].id=i;
N=max(N,r);
}
build(1,1,N);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=N;i++) update(1,1,N,i,N,-k);
for(int i=1;i<=n;i++) update(1,1,N,a[i].r,N,a[i].p);
ll res=-inf;
int L,R;
for(int i=1,j=1;i<=N;i++){
while(j<=n&&i>a[j].l){
update(1,1,N,a[j].r,N,-a[j].p);
j++;
}
if(res<mx[1]){
res=mx[1];L=i;
}
update(1,1,N,i,N,k);
}
if(res<=0){
puts("0");
}else{
build(1,1,N);
for(int i=L;i<=N;i++) update(1,1,N,i,N,-k);
sort(a+1,a+n+1,cmp2);
for(int i=1;i<=n;i++){
if(a[i].l>=L) update(1,1,N,a[i].r,N,a[i].p),R=a[i].r;
if(res==mx[1]) break;
}
tot=0;
for(int i=1;i<=n;i++)
if(a[i].l>=L&&a[i].r<=R) ans[tot++]=a[i].id;
printf("%I64d %d %d %d\n",res,L,R,tot);
for(int i=0;i<tot-1;i++) printf("%d ",ans[i]);
printf("%d\n",ans[tot-1]);
}
return 0;
}