zoukankan      html  css  js  c++  java
  • luogu2178/bzoj4199 品酒大会 (SA+单调栈)

    他要求的就是lcp(x,y)>=i的(x,y)的个数和a[x]*a[y]的最大值

    做一下后缀和,就只要求lcp=i的了

    既然lcp(x,y)=min(h[rank[x]+1],..,[h[rank[y]]])

    那么我们求出来对于每一个h,以它作为最小值的区间的左右端点就可以了,这个可以用单调栈,具体做法见Neat Tree(?哪里具体了)

    假设L是i左面第一个h小于等于它的,R是i右面第一个小于它的(一定要一边有=一边没有,很关键)

    那就相当于lcp(x,y)=h[i] ,rank[x]∈[L,i-1],rank[y]∈[i,R-1]

    数量就是这两个区间大小乘一下,最大值是max(最大值之积,最小值之积)(因为会有负的),这个可以用ST表来做

    貌似并查集也能做 但我哪会啊

    写的这么辣鸡 开着O2才勉强水过洛谷 哪敢到bzoj去交啊

    upd:(Time Limit: 10 Sec)

      1 #include<bits/stdc++.h>
      2 #define pa pair<ll,ll>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 using namespace std;
      5 typedef long long ll;
      6 const int maxn=3e5+10;
      7 const ll inf=1e18;
      8 
      9 inline ll rd(){
     10     ll x=0;char c=getchar();int neg=1;
     11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     12     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     13     return x*neg;
     14 }
     15 
     16 int N,M,deli[maxn],sa[maxn<<1],rnk[maxn<<1],rnk1[maxn<<1],tmp[maxn<<1],h[maxn<<1],cnt[maxn];
     17 ll ans2[maxn],ma[maxn][20],mn[maxn][20],dt[maxn];
     18 int stk[maxn],sh,rg[maxn];
     19 char s[maxn];
     20 
     21 inline void setsa(){
     22     int i,j=0,k;
     23     for(i=1;i<=N;i++) cnt[s[i]]=1;
     24     for(i=1;i<=M;i++) cnt[i]+=cnt[i-1];
     25     for(i=N;i;i--) rnk[i]=cnt[s[i]];
     26     for(k=1;j!=N;k<<=1){
     27         // printf("%d %d %d
    ",M,k,j);
     28         CLR(cnt,0);
     29         for(i=1;i<=N;i++) cnt[rnk[i+k]]++;
     30         for(i=1;i<=M;i++) cnt[i]+=cnt[i-1];
     31         for(i=N;i;i--) tmp[cnt[rnk[i+k]]--]=i;
     32         CLR(cnt,0);
     33         for(i=1;i<=N;i++) cnt[rnk[i]]++;
     34         for(i=1;i<=M;i++) cnt[i]+=cnt[i-1];
     35         for(i=N;i;i--) sa[cnt[rnk[tmp[i]]]--]=tmp[i];
     36         memcpy(rnk1,rnk,sizeof(rnk));
     37         i=2;rnk[sa[1]]=j=1;
     38         for(;i<=N;i++){
     39             if(rnk1[sa[i]]!=rnk1[sa[i-1]]||rnk1[sa[i]+k]!=rnk1[sa[i-1]+k]) j++;
     40             rnk[sa[i]]=j;
     41         }M=j;
     42     }
     43     for(i=1;i<=N;i++)
     44         sa[rnk[i]]=i;
     45 }
     46 inline void seth(){
     47     for(int i=1,j=0;i<=N;i++){
     48         if(rnk[i]==1) continue;
     49         if(j) j--;
     50         int x=sa[rnk[i]-1];
     51         while(i+j<=N&&x+j<=N&&s[i+j]==s[x+j]) j++;
     52         h[rnk[i]]=j;
     53     }
     54 }
     55 
     56 inline void setma(){
     57     for(int i=N;i;i--){
     58         ma[i][0]=mn[i][0]=deli[sa[i]];
     59         for(int j=1;i+(1<<j)-1<=N;j++){
     60             int k=i+(1<<(j-1));
     61             ma[i][j]=max(ma[i][j-1],ma[k][j-1]);
     62             mn[i][j]=min(mn[i][j-1],mn[k][j-1]);
     63         }
     64     }
     65 }
     66 
     67 inline pa getma(int l,int r){
     68     int k=log2(r-l+1);
     69     return make_pair(max(ma[l][k],ma[r-(1<<k)+1][k]),min(mn[l][k],mn[r-(1<<k)+1][k]));
     70 }
     71 
     72 void solve(){
     73     for(int i=2;i<=N;i++){
     74         while(sh&&h[stk[sh]]>h[i])
     75             rg[stk[sh--]]=i;
     76         stk[++sh]=i;
     77     }while(sh) rg[stk[sh--]]=N+1;
     78     for(int i=N;i;i--){
     79         while(sh&&h[stk[sh]]>=h[i]){
     80             int r=rg[stk[sh]]-1;
     81             pa x=getma(i,stk[sh]-1),y=getma(stk[sh],r);
     82             ans2[h[stk[sh]]]=max(ans2[h[stk[sh]]],max(x.first*y.first,x.second*y.second));
     83             dt[h[stk[sh]]]+=1ll*(stk[sh]-i)*(r-stk[sh]+1);
     84             sh--;
     85         }
     86         stk[++sh]=i;
     87     }
     88 }
     89 
     90 int main(){
     91     // freopen("testdata.in","r",stdin);
     92     // freopen("aa.out","w",stdout);
     93     int i,j,k;
     94     N=rd();
     95     scanf("%s",s+1);
     96     for(i=1;i<=N;i++)
     97         deli[i]=rd();
     98     M=127;setsa();
     99     seth();
    100     setma();
    101     CLR(ans2,-127);
    102     solve();
    103     for(i=N-1;i>=0;i--) dt[i]+=dt[i+1],ans2[i]=max(ans2[i],ans2[i+1]);
    104     for(i=0;i<N;i++)
    105         printf("%lld %lld
    ",dt[i],dt[i]?ans2[i]:0);
    106     return 0;
    107 }
  • 相关阅读:
    Docker pull镜像过慢解决方法
    BUUCTF pwn一分题目
    SROP例题
    2020 NUPCTF pwn题目
    BJD4th pwn pi
    0RAYS元旦招新赛
    exit_hook在pwn题中的应用
    eclipse导包导不进来
    java算法题每日一练01,java入门简单算法题小练
    解决chrome无法启用印象笔记-剪藏功能
  • 原文地址:https://www.cnblogs.com/Ressed/p/9833287.html
Copyright © 2011-2022 走看看