2020 2.6

t1

题意,用一个错误算法求逆序对,当前数为p[i]则daan+=max(0,i-p[i]);现在有n个数为1-n的排列,已经给出了前m个数,求有好多种排列方法使得该算法答案正确。

题解。

发现如果当前p[i]<=i则要求前面的所有内容都比他小,否则p[i]>i,则要求比他小的的内容全部在他前面,否则加少了。

设f[i][j]表示已经放完了前i个位置,最大的数是j的方案数。可知j>=i。

若j>=i则必能找到一个最小的值放进来f[i][j]+=f[i-1][j]。

考虑放一个大的值j,枚举比这个值小的k。f[i][j]+=f[i-1][k]。

先把已经给出的数预处理好在这样转移即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=205;
const int mo=1e9+7;
int T,a[N],f[N][N],n;
bool book[N];
inline int read()
{
    char c=getchar();
    int x=0,f=1;
    while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return x*f;
}
int main()
{
    T=read();
    while(T--)
    {
        n=read();int m=read();
        memset(a,0,sizeof(a));
        memset(f,0,sizeof(f));f[0][0]=1;
        memset(book,0,sizeof(book));
        int xiao=1;
        for(int i=1;i<=m;i++) a[i]=read();
        for(int i=1;i<=n;i++)
        {
            if(a[i])
            {
                for(int j=0;j<a[i];j++)
                    f[i][a[i]]=(f[i][a[i]]+f[i-1][j])%mo;
                if(xiao==a[i])
                    for(int j=max(i,a[i]+1);j<=n;j++)    
                        f[i][j]=(f[i][j]+f[i-1][j])%mo;
                book[a[i]]=1;
                while(xiao<=n&&book[xiao]==1) xiao++;
            }
            else
            {
                for(int k=1;k<=n;k++)
                    for(int j=0;j<k;j++)
                        f[i][k]=(f[i][k]+f[i-1][j])%mo;
                for(int j=i;j<=n;j++)
                    f[i][j]=(f[i][j]+f[i-1][j])%mo;
            }
        }
        cout<<f[n][n]<<"
";
    }
}
View Code

t2

题意:给出一个字符串,将他的所有子串按字典序排列,q次询问每次询问新串的第k个字符是什么,强制在线。

题解:

使用后缀数组。

先求出height然后将每个后缀分割成几部分顺序加入新串,表示有这一段,重复了几次,从哪儿开头。

求出长度的前缀和然后二分查找出在哪一段,再二分查找出在这一段的哪里即可。

代码如下:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e6+5;
int sa[N],rk[N],n,x[N],y[N],height[N],tong[N],m=135;
char c[N];
struct pigu
{
    int l,r,cnt,pos;
    inline int tot()
    {
        return (l+r)*(r-l+1)/2*cnt;
    }
    inline int query(int cha)
    {
        int lq=l,rq=r,daan=l-1;
        while(lq<=rq) 
        {
              int mid=(lq+rq)>>1;
              if(((1ll*(l+mid)*(mid-l+1))>>1)*cnt<cha) 
            daan=mid,lq=mid+1;
              else rq=mid-1;
        }
        return pos+(cha-((1ll*(l+daan)*(daan-l+1))>>1)*cnt-1)%(daan+1);
    }
}q[N];
inline int read()
{
    char c=getchar();
    int x=0,f=1;
    while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    return x*f;
}
inline void get_sa()
{
    for(int i=1;i<=n;i++) x[i]=c[i],tong[x[i]]++;
    for(int i=1;i<=m;i++) tong[i]+=tong[i-1];
    for(int i=n;i>=1;i--) sa[tong[x[i]]--]=i;
    for(int k=1;k<=n;k<<=1)
    {
        int cnt=0;
        for(int i=n-k+1;i<=n;i++) y[++cnt]=i;
        for(int i=1;i<=n;i++) if(sa[i]>k) y[++cnt]=sa[i]-k;
        memset(tong,0,sizeof(tong));
        for(int i=1;i<=n;i++) tong[x[i]]++;
        for(int i=1;i<=m;i++) tong[i]+=tong[i-1];
        for(int i=n;i>=1;i--) sa[tong[x[y[i]]]--]=y[i];
        memset(y,0,sizeof(y));
        swap(x,y);cnt=0;x[sa[1]]=cnt=1;
        for(int i=2;i<=n;i++)
        {
            if(y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) cnt++;
            x[sa[i]]=cnt;
        }
        if(cnt==n) break;m=cnt;
    }
    for(int i=1;i<=n;i++) rk[sa[i]]=i;
    int dao=0;
    for(int i=1;i<=n;i++)
    {
        if(rk[i]==1) continue;
        if(dao) dao--;
        int hu=sa[rk[i]-1];
        while(c[i+dao]==c[hu+dao]) dao++;
        height[rk[i]]=dao;
    }
}
int pos[N],id[N],cnt1,sum[N];
inline void init()
{
    int top=0;pos[0]=-1;id[0]=id[1]=n+1;
    for(int i=n;i>=1;i--)
    {
        int now=n-sa[i]+1;
        if(now==pos[top]) top--;
        while(height[i]<=pos[top])
        {
            q[++cnt1]=(pigu){pos[top]+1,now,id[top]-i,sa[i]};
            now=pos[top];
            top--;
        }
        if(height[i]<now) q[++cnt1]=(pigu){height[i]+1,now,id[top]-i,sa[i]};
        top++;pos[top]=height[i];id[top]=i;
    }
    for(int i=1;i<=cnt1/2;i++) swap(q[i],q[cnt1-i+1]);
    for(int i=1;i<=cnt1;i++) sum[i]=sum[i-1]+q[i].tot();
    int Q=read(),su=0;
    while(Q--)
    {
        int a=read(),b=read();
        a=(a*su)%b;a++;
        int now=lower_bound(sum+1,sum+cnt1+1,a)-sum;
        now=q[now].query(a-sum[now-1]);
        cout<<c[now]<<"
";
        su+=c[now];
    }
}
signed main()
{
    scanf("%s",c+1);
    n=strlen(c+1);
    get_sa();
    init();
}
View Code
原文地址:https://www.cnblogs.com/betablewaloot/p/12271440.html