zoukankan      html  css  js  c++  java
  • BZOJ 3439 Kpm的MC密码

    倒着建trie,然后主席树来求子树第k大。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define maxn 300500
    using namespace std;
    int n,trie[maxn][27],fath[maxn],cnt=0,tag[maxn],k,rot,kr,dfn[maxn],mx[maxn],times=0,line[maxn];
    int tot=0,ls[maxn<<3],rs[maxn<<3],sum[maxn<<3];
    char s[maxn];
    vector <int> v[maxn],root[maxn];
    void insert(int father,int &now,int l,int x)
    {
        if (!now) {now=++cnt;fath[now]=father;}
        if (!l) {tag[x]=now;v[now].push_back(x);return;}
        insert(now,trie[now][s[l-1]-'a'+1],l-1,x);
    }
    void build(int &now,int left,int right)
    {
        now=++tot;
        if (left==right) return;
        int mid=left+right>>1;
        build(ls[now],left,mid);
        build(rs[now],mid+1,right);
    }
    void modify(int last,int &now,int left,int right,int pos)
    {
        now=++tot;sum[now]=sum[last]+1;
        if (left==right) return;
        int mid=left+right>>1;
        ls[now]=ls[last];rs[now]=rs[last];
        if (pos<=mid) modify(ls[last],ls[now],left,mid,pos);
        else modify(rs[last],rs[now],mid+1,right,pos);
    }
    int ask(int last,int now,int left,int right,int x)
    {
        if (sum[now]-sum[last]<x) return -1;
        if (left==right) return left;
        int mid=left+right>>1,lsum=sum[ls[now]]-sum[ls[last]];
        if (x<=lsum) return ask(ls[last],ls[now],left,mid,x);
        else return ask(rs[last],rs[now],mid+1,right,x-lsum);
    }
    void dfs(int now)
    {
        dfn[now]=mx[now]=++times;line[times]=now;
        for (int i=1;i<=26;i++)
        {
            if (trie[now][i])
            {
                dfs(trie[now][i]);
                mx[now]=max(mx[now],mx[trie[now][i]]);
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%s",s);
            insert(0,rot,strlen(s),i);
        }
        dfs(rot);
        build(kr,1,n);root[0].push_back(1);
        for (int i=1;i<=times;i++)
        {
            int now=line[i];
            if (!v[now].size()) root[i].push_back(root[i-1][root[i-1].size()-1]);
            else
            {
                root[i].push_back(tot+1);modify(root[i-1][root[i-1].size()-1],kr,1,n,v[now][0]);
                for (int j=1;j<v[now].size();j++)
                {
                    root[i].push_back(tot+1);
                    modify(root[i][j-1],kr,1,n,v[now][j]);
                }
            }
        }
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&k);
            int ret=tag[i];
            printf("%d
    ",ask(root[dfn[ret]-1][root[dfn[ret]-1].size()-1],root[mx[ret]][root[mx[ret]].size()-1],1,n,k));
        }
        return 0;
    }
  • 相关阅读:
    ylbtech-LanguageSamples-Indexers_2(索引器)
    ylbtech-LanguageSamples-Indexers(索引器)
    ylbtech-LanguageSamples-Hello World
    ylbtech-LanguageSamples-Generics(泛型)
    Tomcat
    Tomcat中部署WEB项目的四种方法
    解决fonts.gstatic.com无法访问
    关于android的屏幕保持常亮
    求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)
    不用加减乘除实现加法
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6057473.html
Copyright © 2011-2022 走看看