zoukankan      html  css  js  c++  java
  • Gym

    题意:求一个序列中本质不同的连续子序列的最大值之和。

    由于要求“本质不同”,所以后缀数组就派上用场了,可以从小到大枚举每个后缀,对于每个sa[i],从sa[i]+ht[i]开始枚举(ht[0]=0),这样就能不重复不遗漏地枚举出每一个子串。

    但是这样做,最坏情况仍旧是$O(n^2)$的,可能会被卡掉,需要进一步优化。

    对于每个sa[i],设k=sa[i]+ht[i],则问题转化成了求max(s[sa[i]],s[sa[i]+1],...,s[k])+max(s[sa[i]],s[sa[i]+1],...,s[k+1])+...+max(s[sa[i]],s[sa[i]+1],...,s[n-1])。

    可以发现,随着下标的增大,最大值是单调不减的,这启示我们利用单调栈将后缀进行分段,对于每个最大值不同的段求出后缀和,对于每个sa[i],利用RMQ求出s[sa[i],k]中的最大值mx,然后在单调栈上二分找到第一个大于mx的值的下标,将贡献分成左右两部分相加即可。

    一开始可以将初始序列离散化,求出后缀数组后再还原回去,这样复杂度就不依赖于序列元素的大小而只与序列长度有关了,$O(nlogn)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=2e5+10,inf=0x3f3f3f3f;
     5 int s[N],buf1[N],buf2[N],b[N],nb,c[N],n,sa[N],ht[N],rnk[N],ST[N][20],Log[N],sta[N],idx[N],tp;
     6 ll sum[N];
     7 void Sort(int* x,int* y,int m) {
     8     for(int i=0; i<m; ++i)c[i]=0;
     9     for(int i=0; i<n; ++i)++c[x[i]];
    10     for(int i=1; i<m; ++i)c[i]+=c[i-1];
    11     for(int i=n-1; i>=0; --i)sa[--c[x[y[i]]]]=y[i];
    12 }
    13 void da(int* s,int n,int m=1000) {
    14     int *x=buf1,*y=buf2;
    15     x[n]=y[n]=-1;
    16     for(int i=0; i<n; ++i)x[i]=s[i],y[i]=i;
    17     Sort(x,y,m);
    18     for(int k=1; k<n; k<<=1) {
    19         int p=0;
    20         for(int i=n-k; i<n; ++i)y[p++]=i;
    21         for(int i=0; i<n; ++i)if(sa[i]>=k)y[p++]=sa[i]-k;
    22         Sort(x,y,m),p=1,y[sa[0]]=0;
    23         for(int i=1; i<n; ++i)y[sa[i]]=x[sa[i-1]]==x[sa[i]]&&x[sa[i-1]+k]==x[sa[i]+k]?p-1:p++;
    24         if(p==n)break;
    25         swap(x,y),m=p;
    26     }
    27 }
    28 void getht() {
    29     for(int i=0; i<n; ++i)rnk[sa[i]]=i;
    30     ht[0]=0,s[n]=-1;
    31     for(int i=0,k=0; i<n; ++i) {
    32         if(k)--k;
    33         if(!rnk[i])continue;
    34         for(; s[i+k]==s[sa[rnk[i]-1]+k]; ++k);
    35         ht[rnk[i]]=k;
    36     }
    37 }
    38 void build() {
    39     for(int i=0; i<n; ++i)ST[i][0]=s[i];
    40     for(int k=1; k<=Log[n]; ++k)
    41         for(int i=0; i+(1<<k)-1<n; ++i)
    42             ST[i][k]=max(ST[i][k-1],ST[i+(1<<(k-1))][k-1]);
    43 }
    44 int qry(int L,int R) {
    45     int k=Log[R-L+1];
    46     return max(ST[L][k],ST[R-(1<<k)+1][k]);
    47 }
    48 struct QR {
    49     int k,mx;
    50     bool operator<(const QR& b)const {return k<b.k;}
    51 } qr[N];
    52 void push(int x,int i) {
    53     for(; ~tp&&x>=sta[tp]; --tp);
    54     sta[++tp]=x,sum[tp]=(ll)x*(idx[tp-1]-i)+sum[tp-1],idx[tp]=i;
    55 }
    56 int main() {
    57     Log[0]=-1;
    58     for(int i=1; i<N; ++i)Log[i]=Log[i>>1]+1;
    59     int T;
    60     for(scanf("%d",&T); T--;) {
    61         scanf("%d",&n);
    62         for(int i=0; i<n; ++i)scanf("%d",&s[i]);
    63         nb=0;
    64         for(int i=0; i<n; ++i)b[nb++]=s[i];
    65         sort(b,b+nb),nb=unique(b,b+nb)-b;
    66         for(int i=0; i<n; ++i)s[i]=lower_bound(b,b+nb,s[i])-b;
    67         da(s,n,n+10),getht();
    68         for(int i=0; i<n; ++i)s[i]=b[s[i]];
    69         build();
    70         ll ans=0;
    71         for(int i=0; i<n; ++i) {
    72             int k=sa[i]+ht[i];
    73             qr[i]= {k,qry(sa[i],k)};
    74         }
    75         sort(qr,qr+n);
    76         sta[tp=0]=inf,sum[tp]=0,idx[tp]=n;
    77         for(int i=n-1,j=n-1; i>=0; --i) {
    78             int k=qr[i].k,mx=qr[i].mx;
    79             for(; j>=k; --j)push(s[j],j);
    80             int t=lower_bound(sta,sta+tp+1,mx,greater<int>())-sta-1;
    81             ans+=(ll)mx*(idx[t]-k)+sum[t];
    82         }
    83         printf("%lld
    ",ans);
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    Nodejs下载和第一个Nodejs示例
    永久关闭Win10工具栏的TaskbarSearch控件
    对称加密,非对称加密,散列算法,签名算法
    【转】TTL和RS232之间的详细对比
    zlg核心板linux系统中查看系统内存等使用信息
    Power BI后台自动刷新数据报错 The operation was throttled by Power BI Premium because there were too many datasets being processed concurrently.
    剪切板和上传文件内容获取
    CSS, LESS, SCSS, SASS总结
    文字程序
    electron 打包“ERR_ELECTRON_BUILDER_CANNOT_EXECUTE”
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11681118.html
Copyright © 2011-2022 走看看