• BZOJ 3745


    分治.....

    之前就了解过这种分治统计答案的算法,对于当前的区间[l,r],我们考虑过中间的那条线的区间,这种题往往都存在单调性,我们发现min和max都是随位置单调的,我们枚举左端点x,然后维护两个指针p1,p2,表示[mid+1,p1/p2]这个区间的最值大于/小于[x,mid]的最值的最远的p1/p2,那么答案就可以分3段统计,一段是[mid+1,min(p1,p2)],右端点在这一部分的区间的min和max都一样,比较容易求出。另一段是[max(p1,p2)+1,r],在这一部分的区间min和max为[mid+1,y]的最值,考虑答案的式子可以拆成:∑min*max*r-∑min*max*(l-1),那么我们就可以预处理出min*max*r和min*max的前缀和,然后就可以算出这一部分对答案的贡献。最后一段是[min(p1,p2)+1,max(p1,p2)],这个对答案的贡献和上一个和像,维护2个前缀和即可。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define maxn 500005
     6 typedef long long LL;
     7 const int mo=1000000000;
     8 int n,a[maxn];
     9 LL ans,sum1[maxn][2],sum2[maxn][2],sum3[maxn][2];
    10 
    11 inline int read(void)
    12 {
    13     int x=0;
    14     char ch=getchar();
    15     while (ch>'9'||ch<'0') ch=getchar();
    16     while (ch>='0'&&ch<='9')
    17     {
    18         x=x*10+ch-'0';
    19         ch=getchar();
    20     }
    21     return x;
    22 }
    23 
    24 void solve(int l,int r) 
    25 {
    26     if (l==r) 
    27     {
    28         ans=(ans+(LL)a[l]*a[l])%mo;
    29         return;
    30     }
    31     int mid=(l+r)>>1;
    32     int mn=1e9,mx=-1;
    33     sum1[mid][0]=sum1[mid][1]=0;
    34     sum2[mid][0]=sum2[mid][1]=0;
    35     sum3[mid][0]=sum3[mid][1]=0;
    36     for (int i=mid+1;i<=r;i++)
    37     {
    38         mn=min(mn,a[i]);
    39         mx=max(mx,a[i]);
    40         sum1[i][0]=(LL)mn*mx%mo*i%mo;sum1[i][1]=(LL)mn*mx%mo;
    41         sum2[i][0]=(LL)mn*i%mo;sum2[i][1]=mn;
    42         sum3[i][0]=(LL)mx*i%mo;sum3[i][1]=mx;
    43     }
    44     for (int i=mid+2;i<=r;i++) 
    45     {
    46         (sum1[i][0]+=sum1[i-1][0])%=mo;(sum1[i][1]+=sum1[i-1][1])%=mo;
    47         (sum2[i][0]+=sum2[i-1][0])%=mo;(sum2[i][1]+=sum2[i-1][1])%=mo;
    48         (sum3[i][0]+=sum3[i-1][0])%=mo;(sum3[i][1]+=sum3[i-1][1])%=mo;
    49     }
    50     mn=1e9,mx=-1;
    51     int t1=a[mid+1],t2=a[mid+1];
    52     int p1=mid,p2=mid;
    53     for (int i=mid;i>=l;i--) 
    54     {
    55         mn=min(mn,a[i]);mx=max(mx,a[i]);
    56         while (t1>=mn&&p1<r) p1++,t1=min(t1,a[p1+1]);
    57         while (t2<=mx&&p2<r) p2++,t2=max(t2,a[p2+1]);
    58         int tmp=min(p1,p2);
    59         LL w=(LL)(mid+2-i+tmp-i+1)*(tmp-mid)/2;w%=mo;
    60         ans=(ans+w*mn%mo*mx%mo)%mo;
    61         tmp=max(p1,p2)+1;
    62         w=(sum1[r][0]-sum1[tmp-1][0]+mo)%mo;
    63         w=(w-(sum1[r][1]-sum1[tmp-1][1]+mo)%mo*(i-1)%mo+mo)%mo;
    64         ans=(ans+w)%mo;
    65         if (p1<=p2) 
    66         {
    67             w=(sum2[p2][0]-sum2[p1][0]+mo)%mo*mx%mo;
    68             w=(w-(sum2[p2][1]-sum2[p1][1]+mo)%mo*(i-1)%mo*mx%mo+mo)%mo;
    69             ans=(ans+w)%mo;
    70         }
    71         else 
    72         {
    73             w=(sum3[p1][0]-sum3[p2][0]+mo)%mo*mn%mo;
    74             w=(w-(sum3[p1][1]-sum3[p2][1]+mo)%mo*(i-1)%mo*mn%mo+mo)%mo;
    75             ans=(ans+w)%mo;
    76         }
    77     }
    78     solve(l,mid);
    79     solve(mid+1,r);
    80 }
    81 
    82 int main()
    83 {
    84     n=read();
    85     for (int i=1;i<=n;i++) a[i]=read();
    86     solve(1,n);
    87     printf("%lld
    ",ans);
    88     return 0;
    89 }
  • 相关阅读:
    IDEA插件和快捷设置
    漫谈虚拟内存
    漫谈进程和线程
    漫谈计算机语言
    初识Python
    数据库物理设计
    漫谈计算机体系
    数据库逻辑设计
    NLP中几种分词库的简单使用(Python)
    ML————朴素贝叶斯原理和SKlearn相关库
  • 原文地址:https://www.cnblogs.com/lvyouyw/p/6901988.html
Copyright © 2020-2023  润新知