• 2020CCPC绵阳/gym102822 C. Code a Trie 贪心


    2020CCPC绵阳/gym102822 C. Code a Trie

    题意

    随机生成一颗字典树,字典树上每个结点的权值都互不相同,给定(n)个询问串和返回值,问字典树中至少有多少个结点。

    分析

    • 首先我们根据所有query建立字典树并记录(sz[x])表示有多少个询问串经过点(x),那么对于同一个串,答案一定是同一个。

    • 我们对于每一个值

      • 计算对应串的LCA, 然后把LCA标记一下
      • 标记这些串在LCA下面的那个点为一定不存在
    • 每个点只能被一个值标记为LCA,根到LCA一定不能经过不存在的点

    • dfs贪心计算每个子树最少的节点

      • 如果这个点的(sz[x]>=2)

        • 这个点一定要选

        • 如果这个点是LCA,那么它的儿子结点都要选

        • 如果这个点不是LCA,它的儿子中(sz[x]=1)的结点至多有一个不选

      • 如果这个点的(sz[x]=1),它的儿子一定不选

    Code

    #include<bits/stdc++.h>
    #define rep(i,x,n) for(int i=x;i<=n;i++)
    #define per(i,n,x) for(int i=n;i>=x;i--)
    #define sz(a) int(a.size())
    #define rson mid+1,r,p<<1|1
    #define pii pair<int,int>
    #define lson l,mid,p<<1
    #define ll long long
    #define pb push_back
    #define mp make_pair
    #define se second
    #define fi first
    using namespace std;
    const double eps=1e-8;
    const int mod=1e9+7;
    const int N=5e5+10;
    const int inf=1e9;
    int T,n;
    string s[N];
    int a[N],b[N],cnt[N],vis[N],ans;
    int tot,ch[N][30];
    vector<string>g[N];
    bool input(){
        cin>>n;
        int flag=1,m=0;
        rep(i,1,n){
            cin>>s[i]>>a[i];
            m+=sz(s[i]);
        }
        tot=0;
        rep(i,1,n) g[i].clear();
        rep(i,0,m+5) memset(ch[i],0,sizeof ch[i]);
        memset(cnt,0,sizeof(int)*(m+5));
        memset(vis,0,sizeof(int)*(m+5));
        return flag;
    }
    bool gao(vector<string> &v){
        //寻找LCA
        sort(v.begin(), v.end(),[](string x,string y){return sz(x)<sz(y);});
        int len=0;
        for(int i=0;i<sz(v[0]);i++){
            int flag=1;
            for(int j=0;j<sz(v)&&flag;j++){
                if(v[j][i]!=v[0][i]) flag=0;
            }
            if(!flag) break;
            else len=i+1;
        }
        //插入前缀
        int rt=0;
        for(int i=0;i<len;i++){
            cnt[rt]++;
            int c=v[0][i]-'a';
            if(ch[rt][c]==-1) return false;
            if(!ch[rt][c]) ch[rt][c]=++tot;
            rt=ch[rt][c];
        }
        //标记LCA
        if(vis[rt]) return false;
        vis[rt]=1;
        cnt[rt]++;
        //标记不存在结点
        for(int i=0;i<sz(v);i++) if(sz(v[i])>len){
            int c=v[i][len]-'a';
            if(ch[rt][c]>0) return false;
            ch[rt][c]=-1;
        }
        return true;
    }
    void dfs(int u){
        if(cnt[u]>1) ans++;
        int flag=vis[u]==0;
        for(int i=0;i<26;i++){
            int x=ch[u][i];
            if(x==0||x==-1) continue;
            if(cnt[x]==1){
                if(!flag) ans++;
                else flag=0; 
            }else dfs(x);
        }
    }
    void solve(int cas){
        int m=0;
        rep(i,1,n){
            b[++m]=a[i];
        }
        sort(b+1,b+m+1);
        m=unique(b+1,b+m+1)-b-1;
        rep(i,1,n){
            a[i]=lower_bound(b+1,b+m+1,a[i])-b;
            g[a[i]].pb(s[i]);
        }
        for(int i=1;i<=m;i++) if(!gao(g[i])){
            printf("Case #%d: -1
    ",cas);
            return;
        }
        ans=0;
        cnt[0]++;//根节点必须选
        dfs(0);
        printf("Case #%d: %d
    ",cas,ans);
    }
    int main(){
        ios::sync_with_stdio(false);
        cin>>T;
        for(int cas=1;cas<=T;cas++){
            input();
            solve(cas);
        }
        return 0;
    }
    
  • 相关阅读:
    [转]十步完全理解SQL
    [转]Java日期时间使用总结
    [转]Mybatis出现:无效的列类型: 1111 错误
    [转]java.lang.OutOfMemoryError: PermGen space及其解决方法
    [转]Spring3核心技术之事务管理机制
    [转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊
    设计模式之装饰模式
    进程通信
    设计模式之备忘录模式
    设计模式之单例模式
  • 原文地址:https://www.cnblogs.com/xyq0220/p/14013567.html
Copyright © 2020-2023  润新知