HDU6059(两棵字典树)
来源:互联网 发布:淘宝国产高仿手办 编辑:程序博客网 时间:2024/06/13 18:52
Kanade's trio
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 767 Accepted Submission(s): 278
Problem Description
Give you an array A[1..n] ,you need to calculate how many tuples (i,j,k) satisfy that (i<j<k) and ((A[i] xor A[j])<(A[j] xor A[k]))
There are T test cases.
1≤T≤20
1≤∑n≤5∗105
0≤A[i]<230
There are T test cases.
Input
There is only one integer T on first line.
For each test case , the first line consists of one integern ,and the second line consists of n integers which means the array A[1..n]
For each test case , the first line consists of one integer
Output
For each test case , output an integer , which means the answer.
Sample Input
151 2 3 4 5
Sample Output
6题意:让你在所给的序列找出有多少三元组i,j,k满足a[i]xor a[j] < a[j] xor a[k]解题思路:用两棵字典树维护,枚举a[j],j前面序列a[i]用一棵字典树维护,j后面的a[k]用一棵字典树维护,然后对于每个a[j],从他的最高位开始,在两棵树中分别找出这一位不同的位对应的数量,比如当前位是0,则需要在前缀树中找出这一位为0的个数x1, 在后缀树中找出这一位为1的个数x2,所以当前满足a[i] xor a[j] < a[j] xor a[k]的三元组数量是x1 * x2,然后接着往下找下去就行。#include <bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 5e5 + 10;int n;int a[maxn];ll ans[40][2];//表示每一层的结果struct node{ int Next[2]; ll sum;//个数 node(){ memset(Next, -1, sizeof(Next)); sum = 0; }};node Tree1[maxn<<2], Tree2[maxn<<2];int res1, res2;int root1, root2;void cal(int root, int status, int d, int type, int op){ node *Treex, *Treey; if(type == 0) { Treex = Tree1; Treey = Tree2; } else { Treex = Tree2; Treey = Tree1; } if(type == 0)//前缀树 { if(status == 0) { int x1 = Treex[root].Next[0]; int x2 = Treey[root].Next[1]; if(x1 != -1 && x2 != -1) { ll sum1 = Treex[x1].sum; ll sum2 = Treey[x2].sum; ans[d][0] -= sum1 * sum2; ans[d][0] += (sum1 + op * 1) * (sum2); } } else { int x1 = Treex[root].Next[1]; int x2 = Treey[root].Next[0]; if(x1 != -1 && x2 != -1) { ll sum1 = Treex[x1].sum; ll sum2 = Treey[x2].sum; ans[d][1] -= sum1 * sum2; ans[d][1] += (sum1 + op * 1) * (sum2); } } } else { if(status == 0) { int x1 = Treex[root].Next[0]; int x2 = Treey[root].Next[1]; if(x1 != -1 && x2 != -1) { ll sum1 = Treex[x1].sum; ll sum2 = Treey[x2].sum; ans[d][1] -= sum1 * sum2; ans[d][1] += (sum1 + op * 1) * (sum2); } } else { int x1 = Treex[root].Next[1]; int x2 = Treey[root].Next[0]; if(x1 != -1 && x2 != -1) { ll sum1 = Treex[x1].sum; ll sum2 = Treey[x2].sum; ans[d][0] -= sum1 * sum2; ans[d][0] += (sum1 + op * 1) * (sum2); } } }}void Insert(int x, int type, node Tree[], int before){ int root; if(type == 0)//前缀树 { root = root1; } else root = root2; for(int i = 30; i >= 0; i--) { int num = (x>>i)&1; if(Tree[root].Next[num] == -1) { int res; if(type == 0) res = ++res1; else res = ++res2; Tree[root].Next[num] = res; } if(before) cal(root, num, i, type, 1); int id = Tree[root].Next[num]; Tree[id].sum++; root = id; }}void Delete(int x, int type, node Tree[], int before){ int root; if(type == 0)//前缀树 { root = root1; } else root = root2; for(int i = 30; i >= 0; i--) { int num = (x>>i)&1; if(before) cal(root, num, i, type, -1); int id = Tree[root].Next[num]; Tree[id].sum--; root = id; }}void init(){ res1 = res2 = 0; memset(ans, 0, sizeof(ans)); int Maxn = (maxn<<2); for(int i = 0; i < Maxn; i++) { Tree1[i].Next[0] = Tree1[i].Next[1] = -1; Tree2[i].Next[0] = Tree2[i].Next[1] = -1; Tree1[i].sum = 0; Tree2[i].sum = 0; }}void initAns(int r1, int r2, int d){ if(d < 0 || r1 == -1 || r2 == -1) return; int x1 = Tree1[r1].Next[0]; int x2 = Tree2[r2].Next[1]; if(x1 != -1 && x2 != -1) { ans[d][0] += Tree1[x1].sum * Tree2[x2].sum; } initAns(x1, x1, d - 1); x1 = Tree1[r1].Next[1]; x2 = Tree2[r2].Next[0]; if(x1 != -1 && x2 != -1) { ans[d][1] += Tree1[x1].sum * Tree2[x2].sum; } initAns(x1, x1, d - 1);}ll solve(int x){ ll sum = 0; for(int i = 30; i >= 0; i--) { int num = (x>>i)&1; sum += ans[i][num]; } return sum;}int main(){ int T; scanf("%d", &T); while(T--) { scanf("%d", &n); init(); root1 = ++res1; root2 = ++res2; for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); Insert(a[i], 0, Tree1, 0); Insert(a[i], 1, Tree2, 0); } initAns(root1, root2, 30); Delete(a[1], 1, Tree2, 1); for(int i = 2; i <= n; i++) { Delete(a[i], 0, Tree1, 1); } ll ssum = 0; for(int i = 2; i < n; i++) { Delete(a[i], 1, Tree2, 1); ssum += solve(a[i]); Insert(a[i], 0, Tree1, 1); } printf("%lld\n", ssum); } return 0;}
阅读全文
1 0
- HDU6059(两棵字典树)
- HDU6059 Kanade's trio(异或字典树)
- hdu6059 Kanade's trio(字典树)
- HDU6059(01字典树求异或最大值)
- hdu6059 字典树维护数位统计异或对数
- 字典树的两种实现
- 2017多校联合第三场/hdu6059 Kanade's trio(tire tree)
- HDU6059-Kanade's trio
- 字典树(trie)简介以及两种实现
- python——反转字典的两种方法(字典的key和value对换)
- Codevs 4189 字典(字典树Trie)
- UVa 11732 统计使用strcmp()两两比较字符串的总次数 字典树
- 两表表查询 数据字典
- HDU6059 Kanade's trio (Trie)
- 字典树(边改边抄)
- 字典树(Trie)
- 字典树(TrieTree)
- Trie(字典)树
- 有一个整数n,写一个函数f(n),返回0~n之间出现的“1”的个数,例如f(1)=1; f(13)=6(1,10,11,12,13一共6个1),最大的f(n)=n的n是多少
- memcached高可用集群原理及介绍
- 一些疑问
- 大数的四则运算之除法----Java代码实现
- Polya定理学习总结
- HDU6059(两棵字典树)
- JVM从起始到调优系列-1
- hdu1114 完全背包
- Android BroadcastReceiver之自定义无序、有序广播
- jmeter的三种参数化
- Apache服务器访问过慢分析及解决
- [PAT乙级]1013. 数素数 (20)
- form标记
- 化学试剂