CF1250C Trip to Saint Petersburg(线段树)

经典套路题,发现l,r都在变,因此枚举r,找到最小的l即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> pll;
typedef pair<int,int> plll;
const int N=2e5+10;
const int inf=0x3f3f3f3f;
struct node{
    int l,r;
    ll mx;
    ll lazy;
}tr[N<<2];
struct seg{
    ll id,w;
};
vector<seg> num[N];
ll n,k;
plll res[N];
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r,0,0};
    }
    else{
        tr[u]={l,r,0,0};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
}
void pushdown(int u){
    ll x=tr[u].lazy;
    tr[u<<1].mx+=x;
    tr[u<<1|1].mx+=x;
    tr[u<<1].lazy+=x;
    tr[u<<1|1].lazy+=x;
    tr[u].lazy=0;
}
void pushup(int u){
    tr[u].mx=max(tr[u<<1].mx,tr[u<<1|1].mx);
}
void modify(int u,int l,int r,ll x){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].mx+=x;
        tr[u].lazy+=x;
        return ;
    }
    if(tr[u].lazy)
        pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,r,x);
    if(r>mid)
        modify(u<<1|1,l,r,x);
    pushup(u);
}
pll query(int u){
    if(tr[u].l==tr[u].r){
        return {tr[u].mx,tr[u].l};
    }
    if(tr[u].lazy)
        pushdown(u);
    if(tr[u<<1].mx>=tr[u<<1|1].mx){
        return query(u<<1);
    }
    else{
        return query(u<<1|1);
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>k;
    int i;
    ll mx=0;
    for(i=1;i<=n;i++){
        int l,r;
        ll p;
        cin>>l>>r>>p;
        mx=max(mx,1ll*r);
        res[i]={l,r};
        num[r].push_back({l,p});
    }
    ll ans=0;
    build(1,1,mx);
    int l,r;
    for(i=1;i<=mx;i++){
        modify(1,1,i,-k);
        for(auto t:num[i]){
            modify(1,1,t.id,t.w);
        }
        auto t=query(1);
        if(t.first>ans){
            ans=t.first;
            l=t.second,r=i;
        }
    }
    int sz=0;
    if(ans!=0){
        for(i=1;i<=n;i++){
            if(res[i].first>=l&&res[i].second<=r){
                sz++;
            }
        }
    }
    if(ans==0){
        cout<<0<<endl;
        return 0;
    }
    cout<<ans<<" "<<l<<" "<<r<<" "<<sz<<endl;
    if(ans!=0){
        for(i=1;i<=n;i++){
            if(res[i].first>=l&&res[i].second<=r){
                cout<<i<<" ";
            }
        }
    }
    cout<<endl;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/14050822.html