2019牛客多校训练第四场C.sequence(线段树+单调栈+前缀和)

匿名 (未验证) 提交于 2019-12-02 23:55:01

题目传送门

Code

  1 /*2442ms*/   2 #include<bits/stdc++.h>   3 using namespace std;   4 typedef long long ll;   5 const int maxn=3e6+5;   6 const ll inf=0x3f3f3f3f3f3f3f3fLL;   7 ll a[maxn],b[maxn],pre_sum[maxn],L[maxn],R[maxn],sta[maxn];   8 struct node   9 {  10     int l,r;//区间[l,r]  11     ll mx;//区间最大值  12     ll mn;//区间最小值  13 }tree[maxn<<2];//一定要开到4倍多的空间  14 void pushup(int index)  15 {  16     tree[index].mx=max(tree[index<<1].mx,tree[index<<1|1].mx);  17     tree[index].mn=min(tree[index<<1].mn,tree[index<<1|1].mn);  18 }  19 void build(int l,int r,int index)  20 {  21     tree[index].l=l;  22     tree[index].r=r;  23     if(l==r){  24         tree[index].mn=tree[index].mx=pre_sum[l];  25         return;  26     }  27     int mid=(l+r)>>1;  28     build(l,mid,index<<1);  29     build(mid+1,r,index<<1|1);  30     pushup(index);  31 }  32 ll queryMIN(int l,int r,int index)  33 {  34     if(l<=tree[index].l&&r>=tree[index].r)  35         return tree[index].mn;  36     int mid=(tree[index].l+tree[index].r)>>1;  37     ll Min=inf;  38     if(l<=mid)  39         Min=min(queryMIN(l,r,index<<1),Min);  40     if(r>mid)  41         Min=min(queryMIN(l,r,index<<1|1),Min);  42     return Min;  43 }  44 ll queryMAX(int l,int r,int index)  45 {  46     if(l<=tree[index].l&&r>=tree[index].r)  47         return tree[index].mx;  48     int mid=(tree[index].l+tree[index].r)>>1;  49     ll Max=-inf;  50     if(l<=mid)  51         Max = max(queryMAX(l,r,index<<1),Max);  52     if(r>mid)  53         Max = max(queryMAX(l,r,index<<1|1),Max);  54     return Max;  55 }  56 int main()  57 {  58     int n;  59     while(~scanf("%d",&n))  60     {  61         for(int i=1;i<=n;i++)  62             scanf("%lld",&a[i]);  63         for(int i=1;i<=n;i++){  64             scanf("%lld",&b[i]);  65             pre_sum[i]=pre_sum[i-1]+b[i];//求b序列前缀和  66         }  67         build(0,n,1);  68         /*单调栈求左端点L[i]*/  69         int top=0;  70         for(int i=1;i<=n;i++){  71             while(top&&a[i]<=a[sta[top]])  72                 top--;  73             L[i]=(top==0)?1:sta[top]+1;  74             sta[++top]=i;  75         }  76          /*单调栈求右端点R[i]*/  77         top=0;  78         for(int i=n;i>=1;i--){  79             while(top&&a[i]<=a[sta[top]])  80                 top--;  81             R[i]=(top==0)?n:sta[top]-1;  82             sta[++top]=i;  83         }  84           85         ll ans=-inf;  86         for(int i=1;i<=n;i++){  87             ll cnt=0;  88             if(a[i]>0){  89                 cnt=(queryMAX(i,R[i],1)-queryMIN(L[i]-1,i-1,1))*a[i];  90             }  91             else if(a[i]<0){  92                 cnt=(queryMIN(i,R[i],1)-queryMAX(L[i]-1,i-1,1))*a[i];  93             }  94             else if(a[i]==0)  95                 cnt=0;  96             if(cnt>ans)ans=cnt;  97         }  98         printf("%lld\n",ans);  99     } 100     return 0; 101 } 102  103 /* 104 7 105 -519 9794 1664 8189 -295 3471 1104 106 -1796 -3137 7098 -3333 4683 -3968 467 3 107 11811072 108 */ 109 /* 110 18 111 -273 7169 -8145 -6664 -2970 698 8701 -6791 459 -5678 -846 8072 6384 5051 -3606 -4737 -9928 6815 112 1609 -8810 9205 -9129 -1919 -116 -6752 385 4347 614 6261 4399 -8961 1022 -1360 -5074 7825 -122 113 142708545 114 */
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!