2019牛客暑期多校训练营(第四场)C sequence(单调栈+线段树)

题目链接:https://ac.nowcoder.com/acm/contest/884/C

题解:枚举a序列中每个点,以当前的点作为最小值,用单调栈找出当前点到左边能达到的第一个比它小的点,找出当前点到右边能达到的第一个比它小的点,然后建立前缀和的线段树。最后,遍历a中n个点,当a[i]小于0时,等于 在它右边的可行区间找前缀和最小的值 减 在它左边的可行区间找前缀和最大的值,当a[i]大于0时,等于 在它右边的可行区间找前缀和最小的值 减 在它左边的可行区间找前缀和最大的值,比较这n个值,取最大即为答案。

AC代码:

语言:C++ 代码长度:2681 运行时间: 2123 ms 占用内存:267912K

  1 #include<vector>
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cmath>
  5 #include<queue>
  6 #include<stack>
  7 #define numm ch-48
  8 #define pd putchar(' ')
  9 #define pn putchar('\n')
 10 #define pb push_back
 11 #define fi first
 12 #define se second
 13 #define fre1 freopen("1.txt","r",stdin)
 14 #define fre2 freopen("2.txt","w",stdout)
 15 using namespace std;
 16 template <typename T>
 17 void read(T &res) {
 18     bool flag=false;char ch;
 19     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
 20     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
 21     flag&&(res=-res);
 22 }
 23 template <typename T>
 24 void write(T x) {
 25     if(x<0) putchar('-'),x=-x;
 26     if(x>9) write(x/10);
 27     putchar(x%10+'0');
 28 }
 29 const int maxn=3000010;
 30 const int N=1010;
 31 const int inf=0x3f3f3f3f;
 32 typedef long long ll;
 33 struct node {
 34     int l,r;
 35     ll minn,maxx;
 36 }tree[maxn<<2];
 37 ll sum[maxn];
 38 int a[maxn],b[maxn];
 39 int l[maxn],r[maxn];
 40 int n;
 41 void pushup(int cur) {
 42     tree[cur].minn=min(tree[cur<<1].minn,tree[cur<<1|1].minn);
 43     tree[cur].maxx=max(tree[cur<<1].maxx,tree[cur<<1|1].maxx);
 44 }
 45 void build(int l,int r,int cur) {
 46     tree[cur].l=l;
 47     tree[cur].r=r;
 48     if(l==r) {
 49         tree[cur].minn=tree[cur].maxx=sum[l];
 50         return ;
 51     }
 52     int mid=(l+r)>>1;
 53     build(l,mid,cur<<1);
 54     build(mid+1,r,cur<<1|1);
 55     pushup(cur);
 56 }
 57 ll querymax(int ql,int qr,int cur) {
 58     if(ql<=tree[cur].l&&tree[cur].r<=qr)
 59         return tree[cur].maxx;
 60     ll res=-1e18;
 61     if(ql<=tree[cur<<1].r) res=max(querymax(ql,qr,cur<<1),res);
 62     if(qr>=tree[cur<<1|1].l) res=max(querymax(ql,qr,cur<<1|1),res);
 63     return res;
 64 }
 65 ll querymin(int ql,int qr,int cur) {
 66     if(ql<=tree[cur].l&&tree[cur].r<=qr)
 67         return tree[cur].minn;
 68     ll res=1e18;
 69     if(ql<=tree[cur<<1].r) res=min(querymin(ql,qr,cur<<1),res);
 70     if(qr>=tree[cur<<1|1].l) res=min(querymin(ql,qr,cur<<1|1),res);
 71     return res;
 72 }
 73 stack<int> s;
 74 int main()
 75 {
 76     read(n);
 77     for(int i=1;i<=n;i++)
 78         read(a[i]);
 79     for(int i=1;i<=n;i++) {
 80         read(b[i]);
 81         sum[i]=sum[i-1]+(ll)b[i];
 82     }
 83     build(0,n,1);
 84     for(int i=1;i<=n;i++) {
 85         while(!s.empty()&&a[s.top()]>=a[i]) s.pop();
 86         if(s.empty()) l[i]=0;
 87         else l[i]=s.top();
 88         s.push(i);
 89     }
 90     while(!s.empty()) s.pop();
 91     for(int i=n;i>=1;i--) {
 92         while(!s.empty()&&a[s.top()]>=a[i]) s.pop();
 93         if(s.empty()) r[i]=n;
 94         else r[i]=s.top()-1;
 95         s.push(i);
 96     }
 97     ll res=-1e18;
 98     for(int i=1;i<=n;i++) {
 99         int x=a[i];
100         if(x>0)
101             res=max((querymax(i,r[i],1)-querymin(l[i],i-1,1))*(ll)x,res);
102         else if(x<0)
103             res=max((querymin(i,r[i],1)-querymax(l[i],i-1,1))*(ll)x,res);
104     }
105     write(res);pn;
106     return 0;
107 }
View Code

 

猜你喜欢

转载自www.cnblogs.com/wuliking/p/11261576.html