题解:

官方题解太简略了orz

具体实现的方式其实有很多

问题就在于确定A[j]以后,如何找符合条件的A[i]

这里其实就是要提前预处理好

我是倒序插入点的,所以要沿着A[k]爬树,找符合的A[i]

如果发现A[i]与A[k]的第p位不同,比如A[k]位1,A[i]为0,那么所有的在i右边的第p位为0的数就都可以充当A[j]

所以实际上就需要求出有多少点对(i, j),满足这个条件。

不妨用可持久化的思想考虑这个过程

倒序插入A[i]时,我们就能统计出来A[i]的第p位为0(或者为1)时,所有在i右边的第p位为0(或者为1)的数有多少个

但是,问题在于我们需要删除结点

这个过程就要倒着想

如果删除A[i]

1、对于删除的那条字典树的链,链上每个点减少的贡献为 “那个结点的子树大小”

2、对于非链上的点,如果这个点和A[i]相应的第p位相同,那么它减少的贡献也是“这个结点的子树大小”

但注意,1情况对应的子树大小实际上是要减1的,因为被删除了一个结点。

我们用一个数组记录第p位为0或1时删除了几次,就可以处理第二种情况

但是第一种情况是比较特殊的,所以我们对每个结点都记录一下它上次被删除是哪一次

这样就可以做了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <cstdlib>
using namespace std;
const int maxn = 5e5 + ;
typedef long long LL;
struct Node{
Node* ch[];
LL num, ans, Mv;
}pool[maxn*], *null;
int tot, a[maxn], tt = ;
LL Minus[][], Plus[][];
inline Node* newnode(){
Node* x = &pool[tot++];
x->ch[] = x->ch[] = null;
x->num = x->ans = x->Mv = ;
return x;
}
void pre(){
null = newnode();
null->ch[] = null->ch[] = null;
null->num = ;
}
inline void Insert(Node* root, int x){
Node* u = root;
for(int i = ; i >= ; i--){
int c = (x&(<<i)) ? : ;
if(u->ch[c] == null){
u->ch[c] = newnode();
}
u->num++;
u->ch[c]->ans += Plus[i][c];
Plus[i][c]++;
u = u->ch[c];
}
u->num++;
} inline void Erase(Node* root, int x){
Node* u = root;
for(int i = ; i >= ; i--){
int c = (x&(<<i)) ? : ;
u->num--;
Minus[i][c]++;
u->ch[c]->ans -= (Minus[i][c] - u->ch[c]->Mv - )*u->ch[c]->num;
u->ch[c]->ans -= u->ch[c]->num - ;
u->ch[c]->Mv = Minus[i][c];
u = u->ch[c];
}
u->num--;
} inline LL Find(Node* root, int x){
LL ans = ;
Node* u = root;
for(int i = ; i >= ; i--){
int c = (x&(<<i)) ? : ;
LL v = u->ch[c^]->Mv;
LL rnum = u->ch[c^]->ans - (Minus[i][c^]-v)*u->ch[c^]->num;
ans += rnum;
u = u->ch[c];
}
return ans;
} int main()
{
int T; cin>>T;
for(; T; T--){
int n; cin>>n;
LL ans = ;
tot = ; pre();
Node* root = newnode();
memset(Minus, , sizeof(Minus));
memset(Plus, , sizeof(Plus));
for(int i = ; i <= n; i++) scanf("%d", &a[i]);
for(int i = n-; i >= ; i--) Insert(root, a[i]);
for(int i = n; i >= ; i--){
ans += Find(root, a[i]);
Erase(root, a[i-]);
}
cout<<ans<<endl;
}
}

2017 Multi-University Training Contest - Team 3 Kanade's trio(字典树+组合数学)的更多相关文章

  1. 2017 Multi-University Training Contest - Team 3 Kanade's sum hd6058

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=6058 题目: Kanade's sum Time Limit: 4000/2000 MS (J ...

  2. hdu6059 Kanade's trio 字典树+容斥

    转自:http://blog.csdn.net/dormousenone/article/details/76570172 /** 题目:hdu6059 Kanade's trio 链接:http:/ ...

  3. 2017 Multi-University Training Contest - Team 3 RXD and dividing(树)

    题解: 其实贪心地算就可以了 一个最优的分配就是每条边权贡献的值为min(k, sz[x]),sz[x]是指子树的大小 然后最后加起来就是答案. #include <iostream> # ...

  4. 2017 Wuhan University Programming Contest (Online Round) D. Events,线段树区间更新+最值查询!

    D. Events 线段树区间更新查询区间历史最小值,看似很简单的题意写了两天才写出来. 题意:n个数,Q次操作,每次操作对一个区间[l,r]的数同时加上C,然后输出这段区间的历史最小值. 思路:在线 ...

  5. 2017 Multi-University Training Contest - Team 9 1005&&HDU 6165 FFF at Valentine【强联通缩点+拓扑排序】

    FFF at Valentine Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  6. 2017 Multi-University Training Contest - Team 9 1004&&HDU 6164 Dying Light【数学+模拟】

    Dying Light Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Tot ...

  7. 2017 Multi-University Training Contest - Team 9 1003&&HDU 6163 CSGO【计算几何】

    CSGO Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  8. 2017 Multi-University Training Contest - Team 9 1002&&HDU 6162 Ch’s gift【树链部分+线段树】

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  9. 2017 Multi-University Training Contest - Team 9 1001&&HDU 6161 Big binary tree【树形dp+hash】

    Big binary tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)T ...

随机推荐

  1. 汇编:将指定的内存中连续N个字节填写成指定的内容

    1.loop指令实现 ;=============================== ;循环程序设计 ;将制定内存中连续count个字节填写成指定内容(te) ;loop指令实现 DATAS SEG ...

  2. MySQL版本详解

    一.版本说明 1.1.MySQL相关连接 MySQL官网:https://www.mysql.com/ MySQL下载:https://dev.mysql.com/downloads/mirrors/ ...

  3. Redis缓存数据库的安装与配置(2)

    1.为php安装redis客户端扩展 wget https://github.com/nicolasff/phpredis/archive/master.zip tar xf phpredis-mas ...

  4. javascript实现浏览器管理员工具鼠标获取Html元素 并生成 xpath

    javascript实现浏览器管理员工具鼠标获取Html元素 并生成 xpath 看看标题就被吓尿了,够长吧.让我们看看到底是个什么玩意.. 直接上图: 就是这个东东了,做为一个写爬虫的,有必要了解下 ...

  5. 一个适合变化的产品部署集成包(nginx+jdk+tomcat+nodejs+mysql+redis+mongo+MYSQL主主(读写分离)集群建立+代码包+持续上线+备份)

    一.前言 最近公司做了一套新产品,需要发布到不确定的硬件环境中(不同使用单位规模,使用人数,服务器提供的资源不同)若每次进行人工部署耗时费力,周期过长. 二.分析 具体的部署流程如下: 由上图流程进行 ...

  6. 6.JAVA知识点归纳整理

    一.jdk初识与HelloWord: 二.java基础: 2.1 标识符_关键字_数据类型 2.2 数据类型转换 2.3 程序编写格式 2.4 运算符 2.5 分支与for循环 2.6 while_b ...

  7. ip4addr_ntoa和不可重入函数

    在网络中,有一个转换IP地址到ASIIC字符串的函数,该函数的返回值所指向的ASIIC字符串驻留在静态内存中,所以该函数不可重入. 通俗的讲,在多任务系统中,一个任务执行在调用运行这个函数的时候,其他 ...

  8. Spring MVC - URL路径映射

    1. 普通映射 A. @RequestMapping("/test1") B. @RequestMapping(value={"/test1", "/ ...

  9. 教你用Bootstrap开发漂亮的前端界面

    Bootstrap介绍: Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目. Bootstrap的特点: 一.预处理脚本:虽然可以直 ...

  10. java通过句柄访问对象

    在Java里,任何东西都可看作对象.尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“句柄”(Handle),有的人将其称作一个“引用”,甚至一个“指针”. 主类型的数据成员可直接初始化, ...