题目链接:https://codeforces.com/contest/1250/problem/C
题意:你在城市找工作,有N个工作,每个工作如果从第L天工作到第R天,会得到W的赏金,你可以同时兼职多份工作,但是只要你在这个城市一天,你就会失去K元, 现在让你输出你 的最大盈利,并输出你从第几天到第几天留在这个城市和参加的工作的编号, 如果你无论如何都无法盈利, 输出0。
思路:线段树,先把每天的亏损k元加到线段树上,先把每个工作所得赏金加到该工作的R上,然后把工作按L排序,枚举左端点,如果某个工作a[i].L小于左端点,那就把之前加到a[i].R上的赏金移除掉。一样的再把工作按R排序,再枚举右端点,如果此时最大盈利和枚举左端点时的最大盈利一样大,那就找到右端点了,然后再看哪些工作在这个区间即可。
//#include <bits/stdc++.h> #include<stdio.h> #include<string.h> #include<math.h> #include<string> #include<iostream> #include<algorithm> #include<queue> #include<map> using namespace std; typedef long long ll; const int maxn=200010; int b[maxn]; struct ture { ll l,r,date,laz; } t[maxn*4]; struct node { ll l,r,w; ll id; } a[maxn]; bool cmp(node x,node y) { if(x.l==y.l) return x.r<y.r; return x.l<y.l; } bool cmp1(node x,node y) { return x.r<y.r; } void build(ll p,ll l,ll r) { t[p].l=l; t[p].r=r; t[p].date=t[p].laz=0; if(l==r) return; ll mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); } void update(ll p, ll l, ll r, ll v) { if (t[p].l>=l&&t[p].r<=r) { t[p].date+=v; t[p].laz+=v; return; } ll mid=(t[p].l+t[p].r)/2; if (t[p].laz) { t[p*2].laz+=t[p].laz; t[p*2+1].laz+=t[p].laz; t[p*2].date+=t[p].laz; t[p*2+1].date+=t[p].laz; t[p].laz=0; } if (mid<l) update(p*2+1,l,r,v); else if (mid>=r) update(p*2,l,r,v); else { update(p*2,l,mid,v); update(p*2+1,mid+1,r,v); } t[p].date=max(t[p*2].date,t[p*2+1].date); } int main() { ll n,k,ma=0; cin>>n>>k; for(int i=1;i<=n;i++) { cin>>a[i].l>>a[i].r>>a[i].w; a[i].id=i; ma=max(ma,a[i].r); } build(1,1,ma); sort(a+1,a+n+1,cmp); for(int i=1;i<=ma;i++) update(1,i,ma,-k); for(int i=1;i<=n;i++) update(1,a[i].r,ma,a[i].w); ll x=1,maxx=0,L,R; for(int i=1;i<=ma;i++) { while(i>a[x].l&&x<=n) { update(1,a[x].r,ma,-a[x].w); x++; } if(maxx<t[1].date) { maxx=t[1].date; L=i; } update(1,i,ma,k); } if (maxx<=0) { cout<<"0"<<endl; return 0; } build(1,1,ma); for(int i=L;i<=ma;i++) update(1,i,ma,-k); sort(a+1,a+n+1,cmp1); for(int i=1;i<=n;i++) { if(a[i].l>=L) { update(1,a[i].r,ma,a[i].w); R=a[i].r; } if(t[1].date==maxx) break; } int h=0; for(int i=1;i<=n;i++) { if(a[i].l>=L&&a[i].r<=R) b[++h]=a[i].id; } cout<<maxx<<" "<<L<<" "<<R<<" "<<h<<endl; for(int i=1;i<=h;i++) cout<<b[i]<<" "; cout<<endl; }