Trie树 模板
普通Trie:
struct TRIE{ int trie[MAXN][2],tot,end[MAXN]; TRIE(){tot=1;} void insert(char *s){//s为要插入的字符串 int len=strlen(s); int u=1;//1为根节点 for(int i=0;i<len;i++){ int c=s[i]-'a';//'a'有时需换成'A'或'0' if(!trie[u][c])//没有共同前缀,建立一个新的 trie[u][c]=++tot;//tot为总点数 u=trie[u][c];//继续向下插入单词 } end[u]=true;//标记是一个出现过的单词(图中涂红色) } //查找单词是否是词典中某单词的前缀 bool find1(char *s){//s为要查找的字符串 int len=strlen(s); int u=1;//1为根节点 for(int i=0;i<len;i++){ int c=s[i]-'a';//'a'有时需换成'A'或'0' if(!trie[u][c])//单词没有出现,直接返回false return false; u=trie[u][c];//继续向下查找单词 } //如果扫描完了这个单词 return true;//是某个单词的前缀 } //查找单词是否在词典中出现过 bool find2(char *s){//s为要查找的字符串 int len=strlen(s); int u=1;//1为根节点 for(int i=0;i<len;i++){ int c=s[i]-'a';//'a'有时需换成'A'或'0' if(!trie[u][c])//单词没有出现,直接返回false return false; u=trie[u][c];//继续向下查找单词 } //如果扫描完了这个单词 return end[u];//如果出现过,返回true;如果没有出现过(是前缀),返回false } }Trie;
01Trie:
struct TRIE_01{ int trie[MAXN*32][2],tot,end[MAXN*32]; TRIE_01(){tot=1;} void insert(int x){ int root=1; for(int i=32;i>=0;i--){ int t=((x>>i)&1); if(!trie[root][t]) trie[root][t]=++tot; root=trie[root][t]; } end[root]=x; } int query(int x){ //查询所有数中和 x异或结果最大的数 int root=1; for(int i=32;i>=0;i--){ int v=(x>>i)&1; //利用贪心策略,优先寻找和当前位不同的数 if(trie[root][v^1]) root=trie[root][v^1]; else root=trie[root][v]; } return end[root]; //返回结果 } }Trie_01;
它还可以有平衡树的作用:
题目就是普通平衡树
#include <cstdio> #include <algorithm> #include <cstring> #define setIO(s) freopen(s".in","r",stdin) #define maxn 100010 * 33 using namespace std; int root=1,tot=1,sumv[maxn],n,opt,x,ch[maxn][2]; void ins(int val,int c){ val += (int)1e7; for(int i=31,p=root,t;i>=0;--i){ t=(val>>i)&1; if(!ch[p][t]) ch[p][t]=++tot; p=ch[p][t]; sumv[p]+=c; } } int rank(int val){ val += (int)1e7; int res=0,p=root; for(int i=31;i>=0;--i){ int t=(val>>i)&1; if(t) res += sumv[ch[p][0]]; p=ch[p][t]; } return res; struct TRIE_01{ int trie[MAXN*32][2],tot,end[MAXN*32]; TRIE_01(){tot=1;} void insert(int x){ int root=1; for(int i=32;i>=0;i--){ int t=((x>>i)&1); if(!trie[root][t]) trie[root][t]=++tot; root=trie[root][t]; } end[root]=x; } int query(int x){ //查询所有数中和 x异或结果最大的数 int root=1; for(int i=32;i>=0;i--){ int v=(x>>i)&1; //利用贪心策略,优先寻找和当前位不同的数 if(trie[root][v^1]) root=trie[root][v^1]; else root=trie[root][v]; } return end[root]; //返回结果 } }Trie_01; } int kth(int val){ int k=root,res=0; for(int i=31;i>=0;--i){ if(val>sumv[ch[k][0]]) res|=(1<<i),val-=sumv[ch[k][0]],k=ch[k][1]; else k=ch[k][0]; } res-=(1e7); return res; } int main(){ //setIO("input"); scanf("%d",&n); while(n--){ scanf("%d%d",&opt,&x); if(opt==1) ins(x,1); else if(opt==2) ins(x,-1); else if(opt==3) printf("%d\n",rank(x)+1); else if(opt==4) printf("%d\n",kth(x)); else if(opt==5) printf("%d\n",kth(rank(x))); else if(opt==6) printf("%d\n",kth(rank(x+1)+1)); } return 0; }