Trip to Saint Petersburg

题目链接: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;
}

猜你喜欢

转载自www.cnblogs.com/zcb123456789/p/12622233.html
今日推荐