题意:给你一个数字 n ,然后 n 组输入,如果第一个字符是+,就把后面的那个数字加入到集合里面去,如果第一个字符是减号,就把后面的那个数字从集合里面去掉一个,如果是问好,就开始配对,看看有多少个数字是和问号后面的数字是匹配的,是否配对的规则是,问好后面的数字都是二进制,一表示奇数,零表示偶数,如果集合中的数字长度和二进制的输入长度不一样,就把短的那个在前面加零,比如,二进制是101,集合中的数字是12,那就是101和012匹配,如果二进制是11,集合中的数字是12345,那么就是00011和12345匹配,奇偶数的位置要一样。
思路:用字典树来进行增删查的操作,并且每次把数字插入进字典树的时候,都要把数字补齐成18位,然后从左边开始插入进字典树,并且插入的时候按照奇偶数的位置把偶数换成零,把奇数换成一插入进字典树,查询的时候也是要把二进制补齐成18位,然后进行查询,删除的时候也是要把数字处理成01串。
p.s.这道题有两种做法,一种就是用字典树来进行增删查,还有一种就是把每个数都换成01串之后再处理成十进制,然后用数组标记的做法来进行增删查用字典树:
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<vector> 7 #include<string> 8 #include<queue> 9 #include<map> 10 #include<stack> 11 #include<set> 12 #define ll long long 13 #define maxn 100010 14 #define PI acos(-1.0) //圆周率 15 const ll INF = 1e18; 16 using namespace std; 17 struct node 18 { 19 int sz; 20 int ch[45*maxn][3]; 21 int sum[45*maxn]; 22 23 void trie() 24 { 25 sz=1; 26 memset(ch,0,sizeof(ch)); 27 memset(sum,0,sizeof(sum)); 28 } 29 30 void add(string x) 31 { 32 int len=x.length(); 33 int k=18-len; 34 int u=0; 35 for(int i=0;i<k;i++) 36 { 37 if(ch[u][0]==0) ch[u][0]=sz++; 38 u=ch[u][0]; 39 } 40 for(int i=0;i<len;i++) 41 { 42 int f=x[i]-'0'; 43 int t=0; 44 if(f%2==0) t=0; 45 else t=1; 46 47 if(ch[u][t]==0) ch[u][t]=sz++; 48 u=ch[u][t]; 49 } 50 51 sum[u]++; 52 } 53 54 void del(string x) 55 { 56 int len=x.length(); 57 int u=0; 58 int k=18-len; 59 60 for(int i=0;i<k;i++) 61 { 62 if(ch[u][0]==0) ch[u][0]=sz++; 63 u=ch[u][0]; 64 } 65 66 for(int i=0;i<len;i++) 67 { 68 int f=x[i]-'0'; 69 int t=0; 70 if(f%2==0) t=0; 71 else t=1; 72 73 if(ch[u][t]==0) ch[u][t]=sz++; 74 u=ch[u][t]; 75 } 76 77 sum[u]--; 78 } 79 80 int query(string x) 81 { 82 int len=x.length(); 83 int u=0; 84 int k=18-len; 85 86 for(int i=0;i<k;i++) u=ch[u][0]; 87 88 for(int i=0;i<len;i++) 89 { 90 int t=x[i]-'0'; 91 u=ch[u][t]; 92 } 93 94 return sum[u]; 95 } 96 }st; 97 int n; 98 string s; 99 char fu[3]; 100 int main() 101 { 102 scanf("%d",&n); 103 st.trie(); 104 for(int i=0;i<n;i++) 105 { 106 scanf("%s",fu); 107 cin>>s; 108 109 if(fu[0]=='+') st.add(s); 110 else if(fu[0]=='-') st.del(s); 111 else printf("%d ",st.query(s)); 112 } 113 114 return 0; 115 }
用数组标记:
1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<math.h> 5 #include<algorithm> 6 #include<vector> 7 #include<string> 8 #include<queue> 9 #include<map> 10 #include<stack> 11 #include<set> 12 #define ll long long 13 #define maxn 100010 14 #define PI acos(-1.0) //圆周率 15 const ll INF = 1e18; 16 using namespace std; 17 ll num[45*maxn]; 18 int n; 19 int main() 20 { 21 scanf("%d",&n); 22 ll k; 23 char s[3]; 24 for(int i=0;i<n;i++) 25 { 26 scanf("%s %I64d",s,&k); 27 int cnt=0; 28 int f=0; 29 ll ans=0; 30 while(k) 31 { 32 cnt=k%10; 33 k/=10; 34 if(cnt%2!=0) ans+=(ll)pow(2,f); 35 f++; 36 } 37 38 if(s[0]=='+') num[ans]++; 39 else if(s[0]=='-') num[ans]--; 40 else printf("%d ",num[ans]); 41 } 42 43 return 0; 44 }