题目链接:https://codeforces.com/contest/1250/problem/C
题目大意:给出一个无限长度的数轴。数轴上的每个点的权值都为-k。其中有n个奖励区间。即选取一个区间后,如果该区间覆盖奖励区间,则区间之和会加上奖励区间的分数。求一个区间的最大分数,输出这个区间和覆盖的奖励区间。
思路:由于奖励区间的范围比较小,所以很容易想到,枚举右端点r,找到左端点l,维护奖励值。从左到右,每读入一个点,首先将[1,r]区间都-k。然后再判断是否r是一个奖励区间的右端点。如果有新加的奖励区间,则所有i<l处的区间都+val,表示前面的去缉拿都可以获得这个奖励值。然后区间查询最值就好了。
ACCode:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand((unsigned)time(NULL));rand();
#include<map>//unordered_map
#include<set>//multiset
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=2e5+10;
//const int MAXM=10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)
struct SegTree{
struct Tree{
int l,r,len;
ll val,maxval;int pos;
ll lazy;
};
Tree T[MAXN<<2];
void PushUp(int rt){
T[rt].val=T[rt<<1].val+T[rt<<1|1].val;
T[rt].maxval=max(T[rt<<1].maxval,T[rt<<1|1].maxval);
if(T[rt<<1].maxval>T[rt<<1|1].maxval) T[rt].pos=T[rt<<1].pos;
else T[rt].pos=T[rt<<1|1].pos;
}
void PushDown(int rt){
if(T[rt].lazy!=0){
T[rt<<1].lazy+=T[rt].lazy;
T[rt<<1|1].lazy+=T[rt].lazy;
T[rt<<1].maxval+=T[rt].lazy;
T[rt<<1|1].maxval+=T[rt].lazy;
T[rt<<1].val+=T[rt].lazy*T[rt<<1].len;
T[rt<<1|1].val+=T[rt].lazy*T[rt<<1|1].len;
T[rt].lazy=0;
}
}
void Build(int l,int r,int rt){
T[rt].l=l;T[rt].r=r;T[rt].len=r-l+1;
T[rt].lazy=0;
if(l==r){
T[rt].maxval=0;//T[rt].val=0;
T[rt].pos=l;
return ;
}
int mid=(l+r)>>1;
Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1);
PushUp(rt);
}
void Update(int ql,int qr,ll val,int rt){
if(ql<=T[rt].l&&T[rt].r<=qr){
// T[rt].val+=val*T[rt].len;
T[rt].maxval+=val;
T[rt].lazy+=val;
return ;
}PushDown(rt);
if(qr<=T[rt<<1].r) Update(ql,qr,val,rt<<1);
else if(ql>=T[rt<<1|1].l) Update(ql,qr,val,rt<<1|1);
else{
Update(ql,qr,val,rt<<1);
Update(ql,qr,val,rt<<1|1);
}PushUp(rt);
}
PLL QueryMax(int ql,int qr,int rt){
if(ql<=T[rt].l&&T[rt].r<=qr) return make_pair(T[rt].maxval,T[rt].pos);
PushDown(rt);
if(qr<=T[rt<<1].r) return QueryMax(ql,qr,rt<<1);
else if(ql>=T[rt<<1|1].l) return QueryMax(ql,qr,rt<<1|1);
else{
PLL tmpl=QueryMax(ql,qr,rt<<1),tmpr=QueryMax(ql,qr,rt<<1|1);
if(tmpl.first>tmpr.first) return tmpl;
else return tmpr;
}
}
};
struct Line{
int l,r,id;
ll val;
friend int operator < (Line a,Line b){
return a.r<b.r;
}
};
SegTree Seg;
Line In[MAXN];
int Ans[MAXN],Acnt;
int n;ll k;
int main(){
while(~scanf("%d%lld",&n,&k)){
for(int i=1;i<=n;++i){
scanf("%d%d%lld",&In[i].l,&In[i].r,&In[i].val);In[i].id=i;
}sort(In+1,In+1+n);
int tmp=In[n].r;
Seg.Build(1,tmp,1);
ll ans=0;int ansl,ansr;
for(int i=1,j=1;i<=tmp&&j<=n;++i){
Seg.Update(1,i,-k,1);//前面任何一个左端点,带上这个点的值
while(In[j].r==i){//有满足的区间
Seg.Update(1,In[j].l,In[j].val,1);
++j;
}
PLL res=Seg.QueryMax(1,i,1);
if(res.first>ans){
ans=res.first;ansl=res.second;ansr=i;
}
}
if(ans==0){
printf("0\n");continue ;
}
printf("%lld %d %d ",ans,ansl,ansr);
Acnt=0;
for(int i=1;i<=n;++i){
int l=In[i].l,r=In[i].r,id=In[i].id;
if(ansl<=l&&r<=ansr) Ans[++Acnt]=id;
}printf("%d\n",Acnt);
for(int i=1;i<=Acnt;++i){
printf("%d%c",Ans[i],i==Acnt?'\n':' ');
}
}
}