• 2020/11/04 模拟赛 经典字符串问题


    Description

    给定一个 $1$ 到 $n$ 的排列,分别为$a_1,a_2,cdots a_n$。对于每个数,都可以看成一个字 符串,那么 $n$ 个串就可以根据字典序来排序。 比如字符串“123”小于字符串“124”,而字符串“123”的字典序大于字符串“12”。 现在给出 $q$ 个询问,每个询问的格式形如 $l,r,k$,对于每个询问都需要回答在区 间 $[l,r]$ 中的第 $k$ 小字典序是哪个数

    Solution

    给出一些字符串,求在给定区间内字典序第k小

    先对所有字符串排序

    再套主席树板子

    可惜不能用itoa和atoi,要使用sprintf和sscanf代替

    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    int n,q,a[100005],id[100005],root[100005],cnt,rk[100005];
    struct Node
    {
        char str[20];
        bool operator < (const Node &z)const
        {
            return strcmp(str,z.str)<0;
        }
    }node[100005];
    struct Seg
    {
        int l,r,val;
    }tree[10000005];
    inline int read()
    {
        int f=1,w=0;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return f*w;
    }
    int build(int l,int r)
    {
        int k=++cnt;
        if(l==r)
        {
            return k;
        }
        int mid=l+r>>1;
        tree[k].l=build(l,mid);
        tree[k].r=build(mid+1,r);
        return k;
    }
    int update(int i,int l,int r,int pos)
    {
        int k=++cnt;
        tree[k].l=tree[i].l;
        tree[k].r=tree[i].r;
        tree[k].val=tree[i].val+1;
        if(l==r)
        {
            return k;
        }
        int mid=l+r>>1;
        if(pos<=mid)
        {
            tree[k].l=update(tree[i].l,l,mid,pos);
        }
        if(pos>mid)
        {
            tree[k].r=update(tree[i].r,mid+1,r,pos);
        }
        return k;
    }
    int query(int u,int v,int l,int r,int val)
    {
        if(l==r)
        {
            return l;
        }
        int k=tree[tree[v].l].val-tree[tree[u].l].val,mid=l+r>>1;
        if(val<=k)
        {
            return query(tree[u].l,tree[v].l,l,mid,val);
        }
        if(val>k)
        {
            return query(tree[u].r,tree[v].r,mid+1,r,val-k);
        }
    }
    int main()
    {
        n=read();
        q=read();
        for(int i=1;i<=n;i++)
        {
            a[i]=read();
        }
        for(int i=1;i<=n;i++)
        {
            sprintf(node[i].str,"%d",a[i]);
        }
        sort(node+1,node+n+1);
        for(int i=1;i<=n;i++)
        {
            int x;
            sscanf(node[i].str,"%d",&x); 
            id[x]=i;
            rk[i]=x;
        }
        root[0]=build(1,n);
        for(int i=1;i<=n;i++)
        {
            root[i]=update(root[i-1],1,n,id[a[i]]);
        }
        for(int i=1;i<=q;i++)
        {
            int L=read(),R=read(),K=read();
            if(R-L+1<K)
            {
                puts("-1");
            }
            else
            {
                printf("%lld
    ",rk[query(root[L-1],root[R],1,n,K)]);
            }
        }
        return 0;
    }
    经典字符串问题
  • 相关阅读:
    012 数据类型基础
    013 数据类型:数字类型
    Codeforces 235C Cyclical Quest (后缀自动机)
    BZOJ 4032 Luogu P4112 [HEOI2015]最短不公共子串 (DP、后缀自动机)
    BZOJ 4278 [ONTAK2015]Tasowanie (后缀数组)
    [加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)
    BZOJ 4044 Luogu P4762 [CERC2014]Virus Synthesis (回文自动机、DP)
    BZOJ 2434 Luogu P2414 [NOI2011]阿狸的打字机 (AC自动机、树状数组)
    BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)
    BZOJ 4327 [JSOI2012]玄武密码 (AC自动机)
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14001796.html
Copyright © 2020-2023  润新知