zoukankan      html  css  js  c++  java
  • trie树

    题:http://hihocoder.com/problemset/problem/1014

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int M=1e6+5;
    int g[M][30],sz[M];
    char s[M];
    void dfs(int u){
        for(int i=0;i<26;i++)
            if(g[u][i]){
                dfs(g[u][i]);
                sz[u]+=sz[g[u][i]];
            }
    }
    int main(){
        int n;
        scanf("%d",&n);
        int tot=1;
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            int len=strlen(s);
            int fir=1;
            for(int j=0;j<len;j++){
                if(!g[fir][s[j]-'a'])
                    g[fir][s[j]-'a']=++tot;
                fir=g[fir][s[j]-'a'];        
            }
            sz[fir]++;
        }
        dfs(1);
        int m;
        scanf("%d",&m);
        while(m--){
            scanf("%s",&s);
            int fir=1;
            int len=strlen(s);
            int ans=0;
            for(int j=0;j<len;j++){
                if(!g[fir][s[j]-'a']){
                    ans=0;
                    break;
                }    
                fir=g[fir][s[j]-'a'];
                ans=sz[fir];
            }
            
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    01字典树:

    经典问题:n个数,m个查询,每次查询给一个数,找出在n个树中与m异或最大的数

    题:http://acm.hdu.edu.cn/showproblem.php?pid=4825

    分析:如果是求异或最大的就优先寻找和当前位不同的数,求最小的就优先寻找和当前位相同的数;

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18; 
    const int M=1e5+5;
    const int maxn=26;
    #define pb push_back
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    struct TRIE{
        int val[M*32];
        int trie[M*32][2];
        int tot,root;
        void init(){
            tot=0;
            root=0;
            memset(trie,0,sizeof(trie));
        }
        void insert(int x){
            int now=root;
            for(int i=31;i>=0;i--){
                int id=(x>>i)&1;
                if(!trie[now][id])
                    trie[now][id]=++tot;
                now=trie[now][id];
            }
            val[now]=x;
        }
        int query(int x){
            int now=root;
            for(int i=31;i>=0;i--){
                int id=(x>>i)&1;
                if(trie[now][id^1])
                    now=trie[now][id^1];
                else
                    now=trie[now][id];
            }
            return val[now];
        }
    }Trie;
    int main(){
        int t;
        scanf("%d",&t);
        for(int p=1;p<=t;p++){
            int n,m;
            scanf("%d%d",&n,&m);
            Trie.init();
            for(int i=1;i<=n;i++){
                int x;
                scanf("%d",&x);
                Trie.insert(x);
            }
            printf("Case #%d:
    ",p);
            for(int i=1;i<=m;i++){
                int x;
                scanf("%d",&x);
                printf("%d
    ",Trie.query(x));
            }
        
        }
        return 0;
    }
    View Code

    最长异或路径:树上异或最大路径是多少

    题:https://www.luogu.com.cn/problem/P4551

    分析:俩点之间的异或等于这俩点分别到根节点的异或和的异或值;

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18; 
    const int M=1e5+5;
    const int maxn=26;
    #define pb push_back
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    struct TRIE{
        int val[M*32];
        int trie[M*32][2];
        int tot,root;
        void init(){
            tot=0;
            root=0;
            memset(trie,0,sizeof(trie));
        }
        void insert(int x){
            int now=root;
            for(int i=31;i>=0;i--){
                int id=(x>>i)&1;
                if(!trie[now][id])
                    trie[now][id]=++tot;
                now=trie[now][id];
            }
            val[now]=x;
        }
        int query(int x){
            int now=root;
            for(int i=31;i>=0;i--){
                int id=(x>>i)&1;
                if(trie[now][id^1])
                    now=trie[now][id^1];
                else
                    now=trie[now][id];
            }
            return val[now];
        }
    }Trie;
    int sum[M];
    int head[M],tot,ans;
    struct node{
        int v,w,nextt;
    }e[M<<1];
    void addedge(int u,int v,int w){
        e[tot].v=v;
        e[tot].w=w;
        e[tot].nextt=head[u];
        head[u]=tot++;
    }
    void dfs(int u,int fa){
        ans=max(ans,sum[u]);
        for(int i=head[u];~i;i=e[i].nextt){
            int v=e[i].v;
            if(v!=fa){
                sum[v]=sum[u]^e[i].w;
                dfs(v,u);
            }
        }
    }
    int main(){
        int n;
        scanf("%d",&n);
        memset(head,-1,sizeof(head));
        for(int u,v,w,i=1;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dfs(1,0);
        Trie.init();
        for(int i=1;i<=n;i++)
            Trie.insert(sum[i]);
        for(int i=1;i<=n;i++){
            ans=max(ans,sum[i]^Trie.query(sum[i]));
        }
        printf("%d
    ",ans);
        return 0;
        
    }
    View Code

    题:https://codeforces.com/contest/706/problem/D

    题意:支持插入和删除操作,问与询问x异或和最大的数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include <ctime>
    #include<queue>
    #include<set>
    #include<map>
    #include<list>
    #include<stack>
    #include<iomanip>
    #include<cmath>
    #include<bitset>
    #define mst(ss,b) memset((ss),(b),sizeof(ss))
    ///#pragma comment(linker, "/STACK:102400000,102400000")
    typedef long long ll;
    typedef long double ld;
    #define INF (1ll<<60)-1
    #define Max 80*100000
    using namespace std;
    int num[Max],cnt=1;  //cnt代表的是节点的个数也是每个节点的下标
    int d[Max][2];
    void update(int x){
        int p=1;
        for(int i=30;i>=0;i--){
            if(d[p][(x>>i)&1]==0) d[p][(x>>i)&1]=++cnt;
            p=d[p][(x>>i)&1];
            num[p]++;
        }
    }
    void update1(int x){
        int p=1;
        for(int i=30;i>=0;i--){
            p=d[p][(x>>i)&1];
            num[p]--;
        }
    }
    int query(int x){
        int ans=0;
        int p=1;
        for(int i=30;i>=0;i--){
            int t=(x>>i)&1;
            if(num[d[p][1^t]]) p=d[p][1^t],ans+=(1<<i);
            else p=d[p][t];
        }
        return ans;
    }
    char s[10];
    int x;
    int main(){
        int n;
        scanf("%d",&n);
        update(0);
        for(int i=1;i<=n;i++){
            scanf("%s%d",s,&x);
            if(s[0]=='+'){
                update(x);
            } else if(s[0]=='-'){
                update1(x);
            } else {
                printf("%d
    ",max(query(x),x));
            }
        }
        return 0;
    }
    View Code

    可持久化01字典树:

    经典问题:查询x与区间[L,R]哪个数异或值最大

    题:https://www.luogu.com.cn/problem/P4735

    题意:给定一个非负整数序列 {a},初始长度为n。

       有 m 个操作,有以下两种操作类型:
       1. A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 n+1。
       2. Q l r x:询问操作,你需要找到一个位置 p,满足l<=p<=r,使得:a[p]^a[p+1]^...^a[n]^x 最大,输出最大是多少。

    分析:异或满足可减性,所以可以维护序列的异或前缀和s[ ]

       那么 a[p]^a[p+1]^...^a[n]^x = s[p-1]^s[n]^x
       此时查询转变为:已知val = s[n]^x,求一个p∈[l-1,r-1],使得s[p]^val最大
       所以构建一棵可持久化trie,第i个版本为插入s[i]后的trie树
       查找的时候就拿出第l-2和第r-1棵trie树进行操作

    #include<bits/stdc++.h>
    using namespace std;
    const int M=6e5+5;
    struct TRIE{
        //rt[i]为第i棵字典树的根,sum[i]表示i号节点被访问的次数
        int trie[M*32][2],sum[M*32],val[M*32];
        int rt[M],tot;
        void init(){
            tot=0;
            rt[0]=++tot;
        }
        void insert(int u,int x){
            rt[u]=++tot;
            int now=rt[u],pre=rt[u-1];
    
            for(int i=31;i>=0;i--){
                int id=(x>>i)&1;
                
                trie[now][id]=++tot;
                trie[now][id^1]=trie[pre][id^1];
                now=trie[now][id];
                pre=trie[pre][id];
                sum[now]=sum[pre]+1;
            }
            val[now]=x;
        }
        int query(int l,int r,int x){
            for(int i=31;i>=0;i--){
                int id=(x>>i)&1;
                //优先寻找找与当前位不同的数
                //表明当前节点在[l,r]区间内有数访问过
                if(sum[trie[r][id^1]]-sum[trie[l][id^1]]>0)
                    r=trie[r][id^1],l=trie[l][id^1];
                else
                    r=trie[r][id],l=trie[l][id];
            }
            return val[r]^x;
        }
    }Trie;
    int s[M];
    char op[2];
    int main(){
        int n,m;
    
        scanf("%d%d",&n,&m);
        for(int x,i=1;i<=n;i++){
            scanf("%d",&x);
            s[i]=s[i-1]^x;
            Trie.insert(i,s[i]);
        }
        while(m--){
            scanf("%s",op);
            int x,l,r;
            if(op[0]=='A'){
                scanf("%d",&x);
                n++;
                s[n]=s[n-1]^x;
                Trie.insert(n,s[n]);
            }
            else{
                scanf("%d%d%d",&l,&r,&x);
                l--,r--;
                if(l==0&&r==0)
                    printf("%d
    ",s[n]^x);
                else
                    printf("%d
    ",Trie.query(Trie.rt[max(l-1,0)],Trie.rt[r],s[n]^x));
            }
        }
    }
    View Code
  • 相关阅读:
    OGNL和Struts2标签
    Struts2中使用Servlet API步骤
    Struts2配置详解
    Strust的基础情况
    分页套用
    删除(注意,删除后,后面顶上去,所以id会一直变,所以我们用class来定义,因为id是唯一的)
    搭建SpringMVC+Mybatis框架并实现数据库的操作
    使用映射接口实现数据库的操作
    django 路由系统
    http协议
  • 原文地址:https://www.cnblogs.com/starve/p/12237165.html
Copyright © 2011-2022 走看看