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\n",rk[query(root[L-1],root[R],1,n,K)]);
        }
    }
    return 0;
}
经典字符串问题

 

posted @ 2020-11-18 19:54  QDK_Storm  阅读(105)  评论(0编辑  收藏  举报