C Trip to Saint Petersburg(线段树)

题目链接:https://codeforces.com/contest/1250/problem/C

题意:给定多个区间,以及每个区间对应的价值p;选定一个区间,L,R,能获得的总价值为其所包含的小区间的价值和-k*(R-L+1);求最大总价值。
参考:https://blog.csdn.net/weixin_43851525/article/details/102943189
题解:先把所有的区间都加上,暴力枚举左端点,取最大值。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
const int maxn=200010;
#define ls rt<<1
#define rs rt<<1|1


ll mx[maxn<<2],lazy[maxn<<2];
void pushup(int rt){
    mx[rt]=max(mx[ls],mx[rs]);
}
void pushdown(int rt){
    lazy[ls]+=lazy[rt];
    lazy[rs]+=lazy[rt];
    mx[ls]+=lazy[rt];
    mx[rs]+=lazy[rt];
    lazy[rt]=0;
}
void build(int rt,int l,int r){
    lazy[rt]=0;
    if(l==r){
        mx[rt]=0;//
        return;
    }
    int m=(l+r)>>1;
    build(ls,l,m);
    build(rs,m+1,r);
    pushup(rt);
}
void update(int rt,int l,int r,int a,int b,ll val){
    if(l>=a&&r<=b){
        mx[rt]+=val;
        lazy[rt]+=val;
        return;
    }
    if(lazy[rt]) pushdown(rt);
    int m=(l+r)>>1;
    if(a<=m) update(ls,l,m,a,b,val);
    if(m<b) update(rs,m+1,r,a,b,val);
    pushup(rt);
}
int n;
ll k;
struct node{
    int l,r,id;
    ll p;
}a[maxn];
bool cmp(const node &x,const node &y){
    return x.l<y.l;
}
bool cmp2(const node &x,const node &y){
    return x.r<y.r;
}
int ans[maxn],tot;
int main()
{
    scanf("%d%I64d",&n,&k);
    int l,r;
    ll p;
    int N=0;
    for(int i=1;i<=n;i++){
        scanf("%d%d%I64d",&l,&r,&p);
        a[i].l=l;a[i].r=r;a[i].p=p;
        a[i].id=i;
        N=max(N,r);
    }
    build(1,1,N);
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=N;i++) update(1,1,N,i,N,-k);
    for(int i=1;i<=n;i++) update(1,1,N,a[i].r,N,a[i].p);
    ll res=-inf;
    int L,R;
    for(int i=1,j=1;i<=N;i++){
        while(j<=n&&i>a[j].l){
            update(1,1,N,a[j].r,N,-a[j].p);
            j++;
        }
        if(res<mx[1]){
            res=mx[1];L=i;
        }
        update(1,1,N,i,N,k);
    }
    if(res<=0){
        puts("0");
    }else{
        build(1,1,N);
        for(int i=L;i<=N;i++) update(1,1,N,i,N,-k);
        sort(a+1,a+n+1,cmp2);
        for(int i=1;i<=n;i++){
            if(a[i].l>=L) update(1,1,N,a[i].r,N,a[i].p),R=a[i].r;
            if(res==mx[1]) break;
        }
        tot=0;
        for(int i=1;i<=n;i++)
            if(a[i].l>=L&&a[i].r<=R) ans[tot++]=a[i].id;
        printf("%I64d %d %d %d\n",res,L,R,tot);
        for(int i=0;i<tot-1;i++) printf("%d ",ans[i]);
        printf("%d\n",ans[tot-1]);
    }
    return 0;
}

发布了71 篇原创文章 · 获赞 1 · 访问量 2823

猜你喜欢

转载自blog.csdn.net/weixin_43918473/article/details/103059348