zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    《PS技巧精华全部在这里!》
    c#的dictionary为什么在扩容时会以素数扩容
    初识Lua
    常用的排序
    像gal一样讲故事~
    打枪的实现
    武器的方向,人物和武器的翻转
    虚拟摇杆的修改
    实现虚拟摇杆的移动
    itemPool和MessageCenter
  • 原文地址:https://www.cnblogs.com/zcb123456789/p/12622233.html
Copyright © 2011-2022 走看看