题解:
我们首先枚举每个日期i,对于每个日期,对[1,i]区间内的值减去k,代表新增加了一天花费值
如果有了收入我们就把区间[第一天开始,这个工作开始得日子]加上val。
举个栗子:
首先:
看这张图,我们先假设他没有活干,那么假设经过了6天,每天花费对应的值为上图,
1.如果你在第一天去了那个地方,那么到了第六天,对应得花费就是数字1下面对应得数字
2.如果你在第二天去了那个地方,那么到了第六天,对应得花费就是数字2下面对应得数字
……
6.如果你在第六天去了那个地方,那么到了第六天,对应得花费就是数字6下面对应得数字
这样大概就明白了线段树储是如何储存得了。
其次:
如果我们在第4-6天有一份兼职工作,每天转val元,那么我们把这个工作加在区间[1,4]上,如图所示。
1.如果你在第一天去了那个地方,那么到了第六天,对应得花费就是数字1下面对应得数字
2.如果你在第二天去了那个地方,那么到了第六天,对应得花费就是数字2下面对应得数字
……
6.如果你在第四天去了那个地方,那么到了第六天,对应得花费就是数字4下面对应得数字
这里你可能会思考一个问题,如果工作时间再第七天结束怎么办,其实不必考虑这个问题,因为我们是按照每份工作得结束时间进行枚举得,既然他能加到线段树上去,那么结束时间必定是在这个日期之前结束得。
这个地方需要细品,理解了就会做了
其实这个题可以理解为区间最值查询,并且需要输出最值相对应的区间,所以线段树也要维护一下区间范围。
/*Keep on going Never give up*/ #pragma GCC optimize(3,"Ofast","inline") #include <bits/stdc++.h> const int maxn = 2e5+10; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int mod = 100000000; using namespace std; struct wazxy{ ll l,val,id; wazxy(ll x,ll y,ll z){l=x,val=y,id=z;} }; vector<wazxy> v[maxn]; ll add[maxn<<2]; ll imax[maxn<<2]; ll section[maxn<<2]; void Add(int node,ll val){ add[node]+=val; imax[node]+=val; return ; } void push_down(int node){ //这个跟上面的Add函数都是线段树的lazy操作 if(!add[node]) return; Add(node*2,add[node]); //pushdown Add(node*2+1,add[node]); add[node]=0; } void build(int node,int start,int ends){ //新键线段树,这里新建的目的是要维护左端点值 if(start==ends){ section[node]=start; //更新区间左端的值 return; } int mid=(start+ends)/2; build(node*2,start,mid); build(node*2+1,mid+1,ends); } void update(int node,int start,int ends,int l,int r,ll val){ //更新区间操作 if(start>=l&&ends<=r){ Add(node,val); return; } int mid=(start+ends)/2; push_down(node); if(l<=mid) update(node*2,start,mid,l,r,val); if(r>mid) update(node*2+1,mid+1,ends,l,r,val); //跟平时不同的是,不仅要对最值进行更新, // 同时也需要对每个最值对应的范围进行更新操作 imax[node]=max(imax[node*2],imax[node*2+1]); if(imax[node]==imax[node*2]) section[node]=section[node*2]; //看看这个总的max是取了哪边区间的,对应更新其区间值 else section[node]=section[node*2+1]; } int main(){ ll n,k,ma=0; cin>>n>>k; for(int i=0;i<n;i++){ ll x,y,val; scanf("%lld%lld%lld",&x,&y,&val); v[y].push_back(wazxy(x,val,i+1)); //这里吧y时间结束的的放在一个容器中,避免了排序 ma=max(ma,y); } build(1,1,ma); ll ans=0,l,r; for(int i=1;i<=ma;i++){ update(1,1,ma,1,i,-k); for(auto it : v[i]) update(1,1,ma,1,it.l,it.val); pair<ll,ll> z=make_pair(imax[1],section[1]); if(z.first>ans){ //更新答案区间 ans=z.first,l=z.second,r=i; } } if(ans==0) cout<<0<<endl; else{ vector<ll> aa; for(int i=l;i<=r;i++){ for(auto it : v[i]){ if(it.l>=l) aa.push_back(it.id); } } printf("%lld %lld %lld %d\n",ans,l,r,aa.size()); for(auto it : aa) printf("%lld ",it); cout<<endl; } return 0; }