absi2011's Blog & Daily Life.

全新的开始       我要省选翻盘       I wanna AK in 高考\化学       自此,生无可恋
[破碎的状态] ZOJ 3738
[破碎的状态] [-63] NOI 2015 寿司晚宴

[破碎的状态] [-64] NOI 2015 品酒大会

absi2011 posted @ May 19, 2016 11:37:14 PM in 刷题记录 with tags 字符串 后缀数组 小高考 bzoj uoj , 363 阅读

这一题是个后缀数组

立下flag:在最近的8天里,每日blog至少一更碎碎念

所以,这一题就是求出lcp以后并查集乱搞就行了..

考场上并没想到lcp也是可惜,另外n log2n看起来不是完全不能过..至少uoj和bzoj都过了,lg挂了不明为何

下次写个O(n log n)或者O(n)的试试吧..

lcp的性质也真是神奇..长见识了..

反正这样就是过了..

解法:

1,求lcp

2,倒序求答案

#include<set>
#include<map>
#include<list>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<time.h>
#include<bitset>
#include<vector>
#include<memory>
#include<utility>
#include<stdio.h>
#include<sstream>
#include<fstream>
#include<iostream>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct node
{
    int x;
    int y;
    int id;
    friend bool operator < (const node &a,const node &b)
    {
        return a.y<b.y;
    }
};
node b[300005];
char a[300005];
int n;
int c[300005];
int val[300005];
void suffix_sort(int xx)
{
    if (xx>=n) return;
    int i;
    for (i=0;i<n;i++)
    {
        if ((i==0)||(b[i].x>b[i-1].x)||(b[i].y>b[i-1].y))
        {
            c[b[i].id]=i;
        }
        else
        {
            c[b[i].id]=c[b[i-1].id];
        }
    }
    for (i=0;i<n;i++)
    {
        b[i].x=c[b[i].id];
        if (b[i].id+xx<n)
        {
            b[i].y=c[b[i].id+xx];
        }
        else
        {
            b[i].y=-1;
        }
    }
    int last=0;
    for (i=1;i<n;i++)
    {
        if (b[i].x!=b[i-1].x)
        {
            sort(b+last,b+i);
            last=i;
        }
    }
    sort(b+last,b+i);
    suffix_sort(xx*2);
}
int lcp[300005];
struct nodes
{
    int size;
    int id;
    int max_val1;
    int max_val2;
    int min_val1;
    int min_val2;
    nodes * last;
    nodes * next;
};
struct lcps
{
    int num1;
    int num2;
    int times;
    friend bool operator < (const lcps &a,const lcps &b)
    {
        return a.times>b.times;
    }
};
lcps g[300005];
nodes f[300005];
const int inf=1000000007;
long long ans1[300005];
long long ans2[300005];
int father[300005];
void link(int x,int y,int i)
{
    int temp=x;
    for (;;)
    {
        if (father[temp]==-1) break;
        temp=father[temp];
    }
    for (;x!=temp;)
    {
        int now=father[x];
        father[x]=temp;
        x=now;
    }
    temp=y;
    for (;;)
    {
        if (father[temp]==-1) break;
        temp=father[temp];
    }
    for (;y!=temp;)
    {
        int now=father[y];
        father[y]=temp;
        y=now;
    }
    ans1[i]-=((long long)f[x].size*(f[x].size-1)/2);
    ans1[i]-=((long long)f[y].size*(f[y].size-1)/2);
    f[x].size+=f[y].size;
    ans1[i]+=((long long)f[x].size*(f[x].size-1)/2);
    if (f[y].max_val1>f[x].max_val1)
    {
        f[x].max_val2=f[x].max_val1;
        f[x].max_val1=f[y].max_val1;
    }
    else if (f[y].max_val1>f[x].max_val2)
    {
        f[x].max_val2=f[y].max_val1;
    }
    if (f[y].max_val2>f[x].max_val2)
    {
        f[x].max_val2=f[x].max_val2;
    }
    if (f[y].min_val1<f[x].min_val1)
    {
        f[x].min_val2=f[x].min_val1;
        f[x].min_val1=f[y].min_val1;
    }
    else if (f[y].min_val1<f[x].min_val2)
    {
        f[x].min_val2=f[y].min_val1;
    }
    if (f[y].min_val2<f[x].min_val2)
    {
        f[x].min_val2=f[x].min_val2;
    }
    long long t=max((long long)f[x].max_val1*f[x].max_val2,(long long)f[x].min_val1*f[x].min_val2);
    if (ans1[i]==1)
    {
        ans2[i]=t;
    }
    else if (ans2[i]<t)
    {
        ans2[i]=t;
    }
    f[x].next=f[y].next;
    f[y].next->last=&f[x];
    father[y]=x;
}
int main()
{
    #ifdef absi2011
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    scanf("%d",&n);
    scanf("%s",a);
    n=strlen(a);
    int i;
    for (i=0;i<n;i++)
    {
        b[i].y=a[i];
        b[i].id=i;
        scanf("%d",&val[i]);
    }
    sort(b,b+n);
    suffix_sort(1);
    for (i=0;i<n;i++)
    {
        if ((i==0)||(b[i].x>b[i-1].x)||(b[i].y>b[i-1].y))
        {
            c[b[i].id]=i;
        }
        else
        {
            c[b[i].id]=c[b[i-1].id];
        }
    }
    for (i=0;i<n;i++)
    {
        //printf("%d ",b[i].id+1);
        int last;
        if ((i==0)||(lcp[i-1]==0))
        {
            last=0;
        }
        else
        {
            last=lcp[i-1]-1;
        }
        if (c[i]==0) continue;
        for (;a[last+i]==a[last+b[c[i]-1].id];last++) ;
        lcp[i]=last;
    }
    for (i=1;i<n;i++)
    {
        g[i].num1=b[i-1].id;
        g[i].num2=b[i].id;
        g[i].times=lcp[b[i].id];
    }
    sort(g+1,g+n);
    int j;
    nodes temp;
    memset(father,-1,sizeof(father));
    for (j=0;j<n;j++)
    {
        i=b[j].id;
        if (j!=0) f[i].last=&f[b[j-1].id];
        if (j!=n-1) f[i].next=&f[b[j-1].id];
        f[i].size=1;
        f[i].max_val1=val[i];
        f[i].max_val2=-inf;
        f[i].min_val1=val[i];
        f[i].min_val2=inf;
    }
    f[b[0].id].last=&temp;
    f[b[n-1].id].next=&temp;
    int now=1;
    for (i=n-1;i>=0;i--)
    {
        ans1[i]=ans1[i+1];
        ans2[i]=ans2[i+1];
        for (;now<n;)
        {
            if (g[now].times<i) break;
            link(g[now].num1,g[now].num2,i);
            now++;
        }
    }
    ios::sync_with_stdio(false);
    for (i=0;i<n;i++)
    {
        cout<<ans1[i]<<" "<<ans2[i]<<'\n';
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter