BZOJ 4199: [Noi2015] tasting General Assembly suffix array SA + disjoint-set

Creative Commons License Copyright: Attribution, allow others to create paper-based, and must distribute paper (based on the original license agreement with the same license Creative Commons )

title

BZOJ 4199
LUOGU 2178
Description

The annual "Summer Wine Tasting Club Mirage Congress" grand opening. Assembly includes tasting and fun challenges two aspects, respectively, issued a "chief wine connoisseur" and "chief hunter" two awards to the winners, attracted many sommeliers participate. Dinner on the General Assembly, bartenders Rainbow modulated n cocktail. This cocktail a row n, where i-th wine (≦ i ≦ n) is labeled with a label S_I, each tab 26 is one of lowercase letters. Provided Str (l, r) denotes the l to r th wine glass of wine r-l + 1 label string which are sequentially connected. If Str (p, po) = Str (q, qo), wherein 1≤p≤po≤n, 1≤q≤qo≤n, p ≠ q, po-p + 1 = qo-q + 1 = r, and the second p-called wine is wine q "r ​​similar". Of course, two cups "r similar" (r> 1) it is also a wine "is similar to 1", "2 similar", ......, "(r-1) similar". On the tasting session, sommeliers Freda easily assess the degree of each delicious glass of wine, with its professional standards and experience success captured the "chief wine connoisseur" of the title, the first of which i wine (1≤i≤n) delicious degree a_i. Rainbow announced the challenge now part of the problem: The conference features a cocktail, glass of wine and if the first p q-adjusted against the glass of wine together, will get a glass of delicious wine a_p a_q's degree. Now please sommelier respectively for r = 0,1,2,?, N-1, the statistics of how many ways can select 2 cups "r similar" wine, 2 cups and answer select the "r similar" the maximum value can be adjusted against the wine delicious degrees.

Input

First line of the input file contains a positive integer n, the number of cocktail.
Line 2 contains a string of length n S, wherein the i-th character i represents wine label.
Line 3 containing n integers, separated by a single space between adjacent integers, wherein the integer represents the i-th deliciousness a_i i-glass of wine.
n = 300,000 | a_i | ≤1,000,000,000

Output

Output file comprising n rows. I-th row output two integers, separated by a single space.
1 represents a first integer selected cups "(i-1)" "similar" to the number of wine embodiment,
a maximum of two integer selected cups "(i-1) is similar to" liquor obtained can be adjusted against deliciousness.
If there cups "(i-1) is similar to" wine, the two numbers are zero.

Sample Input

10
ponoiiipoi
2 1 4 7 4 8 3 4 6 7

Sample Output

45 56
10 56
3 32
0 0
0 0
0 0
0 0
0 0
0 0
0 0

Sample Description [1]

P represents a wine glass of wine and the second tuple q (p, q).
Similar 0: All 45 pairs of similar tuples are 0, the maximum degree of taste is 8 × 7 = 56.
Similar 1: (1,8) (2,4) (2,9) (4,9) (5,6) (5,7) (5,10) (6,7) (6,10) (7 , 10), maximum 8 × 7 = 56.
2 is similar: (1,8) (4,9) (5,6), maximum 4 × 8 = 32.
No 3,4,5,?, 9 similar to two glasses of wine, so are the output 0.

analysis

Tune a day, mad. .

solution:

  1. After the first question directly build a suffix array, the interval is calculated for each point contributing, with h e i g h t [ i ] height[i] in ascending update answers.

  2. The second question may be disjoint-set, because it is done from small to large, so the produce section contribution will continue to expand, so that you can contribute each time interval to produce [ l , r ] [l,r] and up, and this section of the elements belonging to only a maximum of two sets, each set is stored in the process and check in at the maximum and minimum values update the current set of answers on the line.

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=3e5+100,inf=LONG_LONG_MAX;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

int n,m=130;
int x[maxn],y[maxn],c[maxn],sa[maxn];
char s[maxn];
inline bool check(int a,int b,int k)
{
    int tmp1=a+k>=n?-1:y[a+k],tmp2=b+k>=n?-1:y[b+k];
    int tmp3=y[a],tmp4=y[b];
    return tmp1==tmp2 && tmp3==tmp4;
}

inline void build_sa()
{
    memset(c,0,sizeof(c));
    for (int i=0; i<=n-1; ++i) c[x[i]=s[i]]++;
    for (int i=1; i<=m-1; ++i) c[i]+=c[i-1];
    for (int i=n-1; i>=0; --i) sa[--c[x[i]]]=i;//初始化
    for (int k=1; k<=n; k<<=1)
    {
        int p=0;
        for (int i=n-k; i<=n-1; ++i) y[p++]=i;
        for (int i=0; i<=n-1; ++i)
            if (sa[i]>=k) y[p++]=sa[i]-k;//根据第二关键字排序
        memset(c,0,sizeof(c));
        for (int i=0; i<=n-1; ++i) c[x[y[i]]]++;
        for (int i=1; i<=m-1; ++i) c[i]+=c[i-1];
        for (int i=n-1; i>=0; --i) sa[--c[x[y[i]]]]=y[i];//根据第一关键字排序
        swap(x,y);
        p=1,x[sa[0]]=0;
        for (int i=1; i<=n-1; ++i) x[sa[i]]= check(sa[i-1],sa[i],k) ?p-1:p++;
        if (p>=n) break;
        m=p;
    }
}

int height[maxn],Rank[maxn];
inline void build_height()
{
    for (int i=0; i<=n-1; ++i) Rank[sa[i]]=i;
    int k=0;height[0]=0;
    for (int i=0; i<=n-1; ++i)
    {
        if (!Rank[i]) continue;
        if (k) --k;
        int j=sa[Rank[i]-1];
        while (j+k<=n && i+k<=n && s[i+k]==s[j+k]) ++k;
        height[Rank[i]]=k;
    }
}

int fa[maxn];
inline int get(int x)
{
    return fa[x]==x?x:fa[x]=get(fa[x]);
}

ll ans[maxn][2],Max[maxn],Min[maxn],siz[maxn];
inline void merge(int x,int y)
{
    int xx=get(x),yy=get(y);

    int k=height[x];
    ans[k][0]+=siz[xx]*siz[yy];
    ans[k][1]=max(max(Max[xx]*Max[yy],Min[xx]*Min[yy]),ans[k][1]);

    Min[xx]=min(Min[xx],Min[yy]);
    Max[xx]=max(Max[xx],Max[yy]);
    fa[yy]=xx;
    siz[xx]+=siz[yy];
}

int a[maxn],id[maxn];
inline void solve()
{
    for (int i=0; i<=n-1; ++i) fa[i]=i,siz[i]=1,Max[i]=Min[i]=a[sa[i]];
    for (int i=0; i<=n-1; ++i)
        if (get(id[i])!=get(id[i]-1)) merge(id[i],id[i]-1);
}

inline bool cmp(int x,int y)
{
    return height[x]>height[y];
}

int main()
{
    read(n);
    scanf("%s",s);
    for (int i=0; i<=n-1; ++i) read(a[i]);
    build_sa();
    build_height();
    for (int i=0; i<=n-1; ++i) id[i]=i,ans[i][0]=0,ans[i][1]=-inf;
    sort(id,id+n,cmp);
    solve();
    for (int i=n-2; i>=0; --i)
    {
        ans[i][0]+=ans[i+1][0];
        ans[i][1]=max(ans[i][1],ans[i+1][1]);
    }
    for (int i=0; i<=n-1; ++i)
        write(ans[i][0]),putchar(' '),write(!ans[i][0]?0:ans[i][1]),puts("");
    return 0;
}

Guess you like

Origin blog.csdn.net/huashuimu2003/article/details/91898869