2017 Multi-University Training Contest - Team 3 Kanade's trio(字典树+组合数学)
题解:
官方题解太简略了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(字典树+组合数学)的更多相关文章
- 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 ...
- hdu6059 Kanade's trio 字典树+容斥
转自:http://blog.csdn.net/dormousenone/article/details/76570172 /** 题目:hdu6059 Kanade's trio 链接:http:/ ...
- 2017 Multi-University Training Contest - Team 3 RXD and dividing(树)
题解: 其实贪心地算就可以了 一个最优的分配就是每条边权贡献的值为min(k, sz[x]),sz[x]是指子树的大小 然后最后加起来就是答案. #include <iostream> # ...
- 2017 Wuhan University Programming Contest (Online Round) D. Events,线段树区间更新+最值查询!
D. Events 线段树区间更新查询区间历史最小值,看似很简单的题意写了两天才写出来. 题意:n个数,Q次操作,每次操作对一个区间[l,r]的数同时加上C,然后输出这段区间的历史最小值. 思路:在线 ...
- 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) ...
- 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 ...
- 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 ...
- 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 ...
- 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 ...
随机推荐
- VULTR的VPS在centos的操作系统中出现网站无法访问 80端口被firewall禁止
导语:叶子在为一位客户配置web服务器环境的时候,出现网站不能访问的情况,但ping正常.客户的服务器是在VULTR上购买的VPS,安装的操作系统为centos 7.3.经过叶子的分析,认为是防火墙阻 ...
- 汇编:采用址表的方法编写程序实现C程序的switch功能
//待实现的C程序 1 void main() { ; -) { : printf("excellence"); break; : printf("good") ...
- jQuery做一个小小的移动图片的位置
样式图点击按钮移动: jQuery代码如下: $(function () { //上 $("#btnUp").click(function () { var ...
- css表格
今天写某个平台的前端数据展示 主要使用表格展示 正好复习总结一下css的表格 首先说说thead.tbody.tfoot <thead></thead> <tbody&g ...
- I/O流、字符集
1)InputStream.OutPutStream是输出输入的基础流,均为抽象类,提供了read和writer方法,所有的子类均实现read和writer方法,read在遇到输入源的结尾时返回-1. ...
- PHP----composer安装和TP5验证码类
妈的,想用TP5做个项目,用到登录验证码了,结果煞笔TP5不内置了,需要用Composer,用吧,来下载 1.安装Composer 1.1 更新 sudo apt-get update 1.2 安装w ...
- CSS3新特性回顾
CSS3 介绍 开始实例 新特征简介 强大的CSS选择器 抛弃图片的视觉效果 盒模型变化(多列布局和弹性盒模型) 阴影效果 Web字体和web Font 图标 CSS33过渡与动画交互效果 媒体查询 ...
- docker学习(三) 安装docker的web可视化管理工具
1.docker是一个一款很轻便的应用容器引擎,为了更好的管理和使用docker,使用web可视化管理工具似乎更符合大多数人的需求.在这里,我给大家分享下自己使用过的几款web工具:docker UI ...
- 15 GIL 全局解释器锁 C语言解决 top ps
1.GIL 全局解释器锁:保证同一时刻只有一个线程在运行. 什么是全局解释器锁GIL(Global Interpreter Lock) Python代码的执行由Python 虚拟机(也叫解释器主循环, ...
- CentOS修改网卡名称
转 一.问题说明 测试环境中出现的小问题,因为虚拟机之间经常复制来复制去,导致网卡配置这块的不一致现象. 配置文件的信息: [root@ora10g network-scripts]# catifcf ...