zoukankan      html  css  js  c++  java
  • NOI2015品酒大会 后缀数组

    自己尝试敲后缀数组,发现难看(tiao)的不行,于是抄了板子

    考虑建出hei以后转化出的问题:

    对于一个数组中权值大于等于k的连续部分,求取两个数的方案数和两数积的最大值

    (好气啊,可以有负数)

    把询问倒序以后相当于连续部分之间会动态加元素,使他们连起来

    维护一段极大连续段的最大值、最小值、长度,保存在左右两端——wtf我也不知道这算什么做法

    然后瞎**乱搞一下,就能每次合并O(1)维护出来了(似乎没比并查集好多少)

      1 #include <bits/stdc++.h>
      2 #define N 300001
      3 #define MIN -9223372036854775807
      4 #define calc(x) (x)*((x)-1)/2
      5 #define ll long long
      6 using namespace std;
      7 ll n,ans,ans2;
      8 ll c[N],mi[N],ma[N],len[N],w[N]; 
      9 ll sa[N],Rank[N],height[N];
     10 ll wa[N],wb[N],wv[N],wd[N];
     11 ll out1[N],out2[N];
     12 struct node
     13 {
     14     ll x,y;
     15     node(ll p,ll q)
     16     {
     17         x=p;y=q;
     18     }
     19     node()
     20     {
     21     }
     22 } t[N];
     23 bool cmp(ll *r,ll a,ll b,ll l)
     24 {
     25     return r[a]==r[b]&&r[a+l]==r[b+l];
     26 }
     27 bool com(node a,node b)
     28 {
     29     return a.x>b.x;
     30 }
     31 void da(ll *r,ll n,ll m)
     32 {
     33     ll *x=wa,*y=wb,*t;
     34     for (ll i=0;i<m;i++) wd[i]=0;
     35     for (ll i=0;i<n;i++) wd[x[i]=r[i]]++;
     36     for (ll i=1;i<m;i++) wd[i]+=wd[i-1];
     37     for (ll i=n-1;i>=0;i--) sa[--wd[x[i]]]=i;
     38     for (ll j=1,p=1,i;p<n;j<<=1,m=p)
     39     {
     40         for (p=0,i=n-j;i<n;i++) y[p++]=i;
     41         for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
     42         for (i=0;i<n;i++) wv[i]=x[y[i]];
     43         for (i=0;i<m;i++) wd[i]=0;
     44         for (i=0;i<n;i++) wd[wv[i]]++;
     45         for (i=1;i<m;i++) wd[i]+=wd[i-1];
     46         for (i=n-1;i>=0;i--) sa[--wd[wv[i]]]=y[i];
     47         for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
     48             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     49     }
     50 }
     51 void get_height(ll *r,ll n)
     52 {
     53     for (ll i=1;i<=n;i++) Rank[sa[i]]=i;
     54         for (ll i=0,k=0,j;i<n;height[Rank[i++]]=k)
     55             for (k?k--:0,j=sa[Rank[i]-1];r[i+k]==r[j+k];k++);
     56 }
     57 void merge(ll x,ll y)
     58 {
     59     if(!len[x] || !len[y]) return;
     60     ans2+=calc(len[x]+len[y]+1)-calc(len[x]+1)-calc(len[y]+1);
     61     ans=max(ans,w[sa[x-len[x]]]*mi[y]);ans=max(ans,mi[x]*mi[y]);
     62     ans=max(ans,w[sa[x-len[x]]]*ma[y]);ans=max(ans,ma[x]*ma[y]);
     63     ll MI=min(mi[x],mi[y]),MA=max(ma[x],ma[y]);
     64     mi[x-len[x]+1]=mi[y+len[y]-1]=MI;
     65     ma[x-len[x]+1]=ma[y+len[y]-1]=MA;
     66     len[x-len[x]+1]=len[y+len[y]-1]=len[x]+len[y];
     67 }
     68 void add(ll now)
     69 {
     70     if(!now) return;
     71     len[now]=1;
     72     mi[now]=ma[now]=w[sa[now]];
     73     ans=max(ans,w[sa[now]]*w[sa[now-1]]);
     74     ++ans2;
     75     if(now)
     76         merge(now-1,now);
     77     if(now<n-1)
     78         merge(now,now+1);
     79 }
     80 int main()
     81 {
     82     scanf("%lld",&n);
     83     for(ll i=0;i<n;i++)
     84     {
     85         char ch;
     86         while(ch=getchar(),!isalpha(ch));
     87         c[i]=ch-'a'+1;
     88     }
     89     for(ll i=0;i<n;i++)
     90         scanf("%lld",&w[i]);
     91     c[n]=0;
     92     da(c,n+1,27);
     93     get_height(c,n);
     94     for(ll i=0;i<n;i++)
     95         sa[i]=sa[i+1],height[i]=height[i+1];
     96     if(0)
     97     for(ll i=0;i<n;i++)
     98     {
     99         printf("%lld %lld
    ",sa[i],height[i]);
    100     }
    101     for(ll i=0;i<n;i++)
    102         t[i]=node(height[i],i);
    103     sort(t,t+n,com);
    104     ll j=0;
    105     ans=MIN;ans2=0;
    106     for(ll i=0;i<n;i++)
    107         len[i]=0,ma[i]=MIN,mi[i]=-MIN;
    108     for(ll i=n-1;i>=0;i--)
    109     {
    110         while(j<n && t[j].x==i) add(t[j].y),j++;
    111         out1[i]=ans2;out2[i]=(ans==MIN)?0:ans;
    112     }
    113     for(ll i=0;i<n;i++)
    114         printf("%lld %lld
    ",out1[i],out2[i]);
    115     return 0;
    116 }
  • 相关阅读:
    C#根据当前时间获取,本周,本月,本季度等时间段
    C#List Dictionary 的初始化方式
    C#List Dictionary 的初始化方式
    DevExpress PivotControl关联ChartControl
    DevExpress PivotControl关联ChartControl
    c#中怎样判断一个程序是否正在运行?
    c#中怎样判断一个程序是否正在运行?
    多线程(五)实战使用并发工具类CyclicBarrier实现并发测试
    多线程(五)实战使用并发工具类CyclicBarrier实现并发测试
    MongoDB查询大于某个时间,小于某个时间,在某一段时间范围
  • 原文地址:https://www.cnblogs.com/wanglichao/p/6845061.html
Copyright © 2011-2022 走看看