D. Yet Another Yet Another Task

题:https://codeforces.com/contest/1359/problem/D

题意:给定一个序列,你可以选择一个区间[L,R],你需要remove掉其中最大的,再sum{L,R},问最大可能是多少。

分析:也就是说,我们可以枚举每个数ai作为最大值,然后再ai左边找前缀和最小的,在ai后边找前缀和最大的,这个用线段树可以实现(简单嘛,也可以用其他数据结构),关键是要在哪些区间选取是最大的,要保证当前ai最大只需要预处理:ai 最左能达到哪个位置使经过的位置的值都比ai小,就可以确定线段树选取的区间了,向右也是一样,这一部分用单调区间的做法即可。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int M=1e5+5;
struct node{
    int mi,mx;
}tr[M<<2];
int a[M],l[M],r[M],sum[M];
void up(int root){
    tr[root].mi=min(tr[root<<1].mi,tr[root<<1|1].mi);
    tr[root].mx=max(tr[root<<1].mx,tr[root<<1|1].mx);
}
void build(int root,int l,int r){
    if(l==r){
        tr[root].mi=tr[root].mx=sum[l];
        return ;
    }
    int midd=(l+r)>>1;
    build(lson);
    build(rson);
    up(root);
}
int querymi(int L,int R,int root,int l,int r){
    if(L<=l&&r<=R){
        return tr[root].mi;
    }
    int midd=(l+r)>>1;
    int res=inf;
    if(L<=midd)
        res=querymi(L,R,lson);
    if(R>midd)
        res=min(res,querymi(L,R,rson));
    return res;
}
int querymx(int L,int R,int root,int l,int r){
    if(L<=l&&r<=R){
        return tr[root].mx;
    }
    int midd=(l+r)>>1;
    int res=-inf;
    if(L<=midd)
        res=querymx(L,R,lson);
    if(R>midd)
        res=max(res,querymx(L,R,rson));
    return res;
}
int main(){
    int n;
    scanf("%d",&n);
    a[1]=0,n++;
    for(int i=0;i<=4*n;i++)
        tr[i].mi=inf,tr[i].mx=-inf;
    for(int i=2;i<=n;i++)
        scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
    build(1,1,n);
    int ans=0;
    for(int i=2;i<=n;i++){
        l[i]=i;
        while(a[l[i]-1]<=a[i]&&l[i]-1>=2){
            l[i]=l[l[i]-1];
        }
    }
    for(int i=n;i>=2;i--){
        r[i]=i;
        while(a[r[i]+1]<=a[i]&&r[i]+1<=n){
            r[i]=r[r[i]+1];
        }
    }
    for(int i=2;i<=n;i++){
        int t1=querymi(l[i]-1,i-1,1,1,n);
        int t2=querymx(i,r[i],1,1,n);
        ans=max(ans,t2-t1-a[i]);
    }
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2020-06-01 15:46  starve_to_death  阅读(193)  评论(0编辑  收藏  举报