题解:

官方题解太简略了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 + 200;
typedef long long LL;
struct Node{Node* ch[2];LL num, ans, Mv;
}pool[maxn*31], *null;
int tot, a[maxn], tt = 0;
LL Minus[32][2], Plus[32][2];
inline Node* newnode(){Node* x = &pool[tot++];x->ch[0] = x->ch[1] = null;x->num = x->ans = x->Mv = 0;return x;
}
void pre(){null = newnode();null->ch[0] = null->ch[1] = null;null->num = 0;
}
inline void Insert(Node* root, int x){Node* u = root;for(int i = 30; i >= 0; i--){int c = (x&(1<<i)) ? 1 : 0;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 = 30; i >= 0; i--){int c = (x&(1<<i)) ? 1 : 0;u->num--;Minus[i][c]++;u->ch[c]->ans -= (Minus[i][c] - u->ch[c]->Mv - 1)*u->ch[c]->num;u->ch[c]->ans -= u->ch[c]->num - 1;u->ch[c]->Mv = Minus[i][c];u = u->ch[c];}u->num--;
}inline LL Find(Node* root, int x){LL ans = 0;Node* u = root;for(int i = 30; i >= 0; i--){int c = (x&(1<<i)) ? 1 : 0;LL v = u->ch[c^1]->Mv;LL rnum = u->ch[c^1]->ans - (Minus[i][c^1]-v)*u->ch[c^1]->num;ans += rnum;u = u->ch[c];}return ans;
}int main()
{int T; cin>>T;for(; T; T--){int n; cin>>n;LL ans = 0;tot = 0; pre();Node* root = newnode();memset(Minus, 0, sizeof(Minus));memset(Plus, 0, sizeof(Plus));for(int i = 1; i <= n; i++) scanf("%d", &a[i]);for(int i = n-1; i >= 1; i--) Insert(root, a[i]);for(int i = n; i >= 3; i--){ans += Find(root, a[i]);Erase(root, a[i-1]);}cout<<ans<<endl;}
}

转载于:https://www.cnblogs.com/Saurus/p/7290186.html

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. 2017 Multi-University Training Contest - Team 1

    2017 Multi-University Training Contest - Team 1 01     签到的 #include<bits/stdc++.h> using names ...

  3. 2017 Multi-University Training Contest - Team 7:1003. Color the chessboard(...)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  4. 2017 Multi-University Training Contest - Team 7:1002. Build a tree(递归)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  5. 2017 Multi-University Training Contest - Team 7:1010. Just do it(组合数?)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  6. 2017 Multi-University Training Contest - Team 7:1008. Hard challenge(模拟)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  7. 2017 Multi-University Training Contest - Team 7:1011. Kolakoski(模拟)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1005. Euler theorem 2017 Multi-University Tr ...

  8. 2017 Multi-University Training Contest - Team 7:1005. Euler theorem(答案是(n+3)/2)

    其他题目题解: 2017 Multi-University Training Contest - Team 7:1003. Color the chessboard 2017 Multi-Univer ...

  9. 2017 Multi-University Training Contest - Team 3:1004. Kanade's trio(01字典树)

    感觉很多时候字典树都是这种题的万能解 (具体规则or什么是字典树:http://blog.csdn.net/jaihk662/article/details/53930927) 建立两棵01字典树,对 ...

  10. 2017 Multi-University Training Contest - Team 2 Puzzle

    题目大意: 给定n, m, p.然后按照一个规则往n*m的方格里填数,最后一个方格是空格,然后玩拼图游戏,问能否复原 规则是:把1~n*m-1的排列中的第1,p+1,2*p+1.....个数依次取出来 ...

最新文章

  1. Linux shell 学习笔记(16)— shell 入门总结
  2. WinForm绘制带有升序、降序的柱形图
  3. 用Python来分析5天破10亿的哪吒,为啥这么火?
  4. R语言ggplot2可视化分组散点图、使用scale_shape_manual函数、scale_color_manual函数、scale_size_manual函自定义设置分组散点的形状、大小、颜色
  5. Matlab简单系统仿真示例1
  6. 编写代码的若干个基本规则(以Java为例)
  7. 20道C#练习题(一)1——10题
  8. noip2014到2017初赛普及组看程序写结果、完善程序
  9. asp.net DataGridTree表格树控件 下拉树 DropTree c# .net
  10. 系统学习NLP(二十七)--EMLo
  11. 人脸验证(四)--CenterLoss
  12. Safari、IE8、iPhone和BlackBerry在Pwn2Own竞赛中被挑落
  13. php xml三级联动,jquery+xml实现三级联动步骤详解
  14. 数据库(表结构)设计技巧及注意事项
  15. 【脚本】一键切换单位与家庭wifi网络环境
  16. linux读和写线程同步,Linux:使用读写锁使线程同步
  17. Anaconda安装torch
  18. matlab 非线性拟合残差,求大神帮助一下关于matlab非线性拟合的问题
  19. 从沟通的一般模型想到互联网,再想到数字媒体,最后想到信息世界
  20. matlab加速模型,matlab仿真加速问题

热门文章

  1. C ++ 的 背 影    ——C++之父Bjarne Stroustrup印象 左轻侯 2002.11.4
  2. Java web--过滤器
  3. ThinkPHP5.0 实现 app支付宝支付功能
  4. SpringMVC学习指南-前言
  5. 源码分析--SDWebImage
  6. TJU_SCS_软件测试_Lab1
  7. android--gradle编译龟速?offline!
  8. OC省字典的数组摘要集
  9. 两个文本框异动任何一个能即时更新计算结果
  10. 远程桌面连接--“发生身份验证错误。要求的函数不受支持