hdu_5589_Tree(莫队+字典树)
题目连接:hdu_5589_Tree
题意:给你一棵树和一些边值,n个点n-1条边,一个m,q个询问,每个询问让你输出在[l,r]区间内任意两点树上的路径的边权异或的和大于m的点对数。
题解:这题很巧妙,看数据知道要用莫队,不过如何来处理树上任意两点的边权异或和大于m呢?我们知道,一个数和另一个数异或两次等于自己,如果我们记录所有的点都与1这个点的路径异或和,不就可以得出任意两点的路径异或和了吗,然后如果我们要用莫队,就要找到增加,删除的时候答案对应的变化,要支持增加删除,并且要找比m大的异或值,01字典树是一个不错的选择,我们考虑如果要找比m大的数,那么在二进制下,前面的位肯定都相同,后面的某一位m为0,当前数为1才有比m大,我们在将异或和插入字典树的时候,转换为二进制,从高位开始插,每插一位,当前的cnt++,表示在当前位为0或者1的数有一个,删除的时候就对应cnt--就行了。
询问:这里设即将插入的数为节点x到1的节点的异或值为sum,我们要和m相比,因为要找比m大的数,而我们此时插入的都是当前节点到根节点的异或和,这里我们就要用到贪心的思想,从高位开始找,当m的当前位为1时,此时你只能找字典树中为与sum当前位异或为1的,如果不找与sum当前位异或为1的那你后面的位无论怎么找,都不能大于m,要与sum当前位异或为1,当sum的当前位为0,应找1这个子节点,当sum当前位为1,应找0这个子节点,所以就是当m的当前位为1时,下一个子节点应为(sum的当前位^1),当m的当前位为0时,直接加上与sum当前位异或为1的子节点的cnt,因为到这一位的时候,与sum当前位异或为1,那后面位与sum异或完后必然是大于m的,所以直接加上当前与sum异或为1的子节点的cnt就行了,然后我们继续搜寻与sum当前为异或为0的下一位,和上面一样,要使与sum当前位异或为0,sum当前位^0=sum当前位。
最后莫队处理完就是结果了
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define F(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long LL;
const int N=;
int M[],va[N],sqr,n,m,k,x,y,z;
LL ans[N];
struct query{
int l,r,id,sq;
bool operator<(const query & b)const{
if(sq==b.sq)return r<b.r;
return sq<b.sq;
}
}q[N];
//-------------------------树的处理-----------------
int g[N],nxt[N<<],w[N<<],v[N<<],eda;
inline void adg(int x,int y,int z){v[++eda]=y,w[eda]=z,nxt[eda]=g[x],g[x]=eda;} void dfs(int u=,int pre=){
for(int i=g[u];i;i=nxt[i])
if(v[i]!=pre)va[v[i]]=w[i]^va[u],dfs(v[i],u);
}
//----------------字典树----------------------------
struct Trie{
int sum[N*][],cnt[N*],ed,c,mc;
void init(){ed=cnt[]=,sum[][]=sum[][]=;}
void insert(int x,int now=){
for(int i=;i>=;i--){
c=x>>i&;
if(!sum[now][c])
sum[now][c]=++ed,cnt[ed]=,sum[ed][]=sum[ed][]=;
now=sum[now][c],cnt[now]++;
}
}
void del(int x,int now=){
for(int i=;i>=;i--)c=x>>i&,now=sum[now][c],cnt[now]--;
}
LL ask(int x,int now=,LL ans=){
for(int i=;i>=;i--){
c=x>>i&,mc=M[i];
if(mc)now=sum[now][c^];
else ans+=cnt[sum[now][c^]],now=sum[now][c];
if(!now)return ans;
}
return ans;
}
}tr; void modui(){
sort(q+,q++k);
int l=,r=;LL ret=;
F(i,,k){
while(r<q[i].r)r++,ret+=tr.ask(va[r]),tr.insert(va[r]);
while(l>q[i].l)l--,ret+=tr.ask(va[l]),tr.insert(va[l]);
while(r>q[i].r)tr.del(va[r]),ret-=tr.ask(va[r]),r--;
while(l<q[i].l)tr.del(va[l]),ret-=tr.ask(va[l]),l++;
ans[q[i].id]=ret;
}
} int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
sqr=(int)sqrt(n);
for(int ee=;ee<=;ee++)M[ee]=(m>>ee)&;
memset(g,,sizeof(g)),eda=;
F(i,,n-)scanf("%d%d%d",&x,&y,&z),adg(x,y,z),adg(y,x,z);
F(i,,k)scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i,q[i].sq=q[i].l/sqr;
dfs(),tr.init(),modui();
F(i,,k)printf("%lld\n",ans[i]);
}
return ;
}
hdu_5589_Tree(莫队+字典树)的更多相关文章
- Codeforces 666E E - Forensic Examination SA + 莫队 + 线段树
E - Forensic Examination 我也不知道为什么这个复杂度能过, 而且跑得还挺快, 数据比较水? 在sa上二分出上下界, 然后莫队 + 线段树维护区间众数. #include< ...
- 洛谷P3246 序列 [HNOI2016] 莫队/线段树+扫描线
正解:莫队/线段树+扫描线 解题报告: 传送门! 似乎是有两种方法的,,,所以分别港下好了QAQ 第一种,莫队 看到这种询问很多区间之类的就会自然而然地想到莫队趴?然后仔细思考一下,发现复杂度似乎是欧 ...
- 【bzoj3289】Mato的文件管理 离散化+莫队算法+树状数组
原文地址:http://www.cnblogs.com/GXZlegend/p/6805224.html 题目描述 Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份 ...
- HDU6534 Chika and Friendly Pairs(莫队,树状数组)
HDU6534 Chika and Friendly Pairs 莫队,树状数组的简单题 #include<bits/stdc++.h> using namespace std; cons ...
- BZOJ 3289: Mato的文件管理[莫队算法 树状数组]
3289: Mato的文件管理 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2399 Solved: 988[Submit][Status][Di ...
- BZOJ3289 Mato的文件管理(莫队算法+树状数组)
题目是区间逆序数查询. 莫队算法..左或右区间向左或右延伸时加或减这个区间小于或大于新数的数的个数,这个个数用树状数组来统计,我用线段树超时了.询问个数和数字个数都记为n,数字范围不确定所以离散化,这 ...
- 洛谷P4689 [Ynoi2016]这是我自己的发明(莫队,树的dfn序,map,容斥原理)
洛谷题目传送门 具体思路看别的题解吧.这里只提两个可能对常数和代码长度有优化的处理方法. I 把一个询问拆成\(9\)个甚至\(16\)个莫队询问实在是有点珂怕. 发现询问的一边要么是一个区间,要么是 ...
- 「洛谷1903」「BZOJ2120」「国家集训队」数颜色【带修莫队,树套树】
题目链接 [BZOJ传送门] [洛谷传送门] 题目大意 单点修改,区间查询有多少种数字. 解法1--树套树 可以直接暴力树套树,我比较懒,不想写. 稍微口胡一下,可以直接来一个树状数组套主席树,也就是 ...
- 【CF633H】Fibonacci-ish II 莫队+线段树
[CF633H]Fibonacci-ish II 题意:给你一个长度为n的序列$a_i$.m个询问,每个询问形如l,r:将[l,r]中的所有$a_i$排序并去重,设得到的新数列为$b_i$,求$b_1 ...
随机推荐
- Power oj2498/DP/递推
power oj 2498 /递推 2498: 新年礼物 Time Limit: 1000 MS Memory Limit: 65536 KBTotal Submit: 12 Accepted: 3 ...
- 学习笔记——迭代器模式Iterator
迭代器模式,使用很多,但是很少实现.常用的集合都支持迭代器. 集合中的CreateIterator()可用于创建自己的迭代器,在里面通过调用迭代器的构造函数Iterator(Aggregate)来绑定 ...
- 第十三节,基本数据类型,数字int字符串str
基本数据类型 数字 int 字符串 str 布尔值 bool 列表 list 元组 tuple 字典 dict 数据类型关系图 查看一个对象的类 如:如查看对象变量a是什么类 用到函 ...
- spark第二篇--基本原理
==是什么 == 目标Scope(解决什么问题) 在大规模的特定数据集上的迭代运算或重复查询检索 官方定义 aMapReduce-like cluster computing framework de ...
- [nginx] 网上最全面nginx教程(近100篇文章整理)
转载:http://bbs.linuxtone.org/thread-25588-1-1.html Nginx基础 1. nginx安装 2. nginx 编译参数详解 3. nginx安装配置 ...
- Linux Ubuntu 内核升级
方法一 : 1 更新系统源 apt-get update 2 搜索内核文件 apt-cache search linux-image 3 安装 apt-get install -y linux-im ...
- postgres-xl 集体搭建(2)
$ pgxc_ctl prepare config minimal 生成一个单机伪分布集群配置简单模板 根据该模板进行简单修改就可以配置成一个集群 $ pgxc_ctl init all $ pgxc ...
- PHP之curl函数相关试题
一.问答题 1.curl_setopt中超时设置,URL设置,post数据接收设置,解压缩设置,HEADER信息设置的参数名分别是什么? 2.curl批量设置参数的函数是什么? 二.编程题 1.封装一 ...
- MySQL 索引 总结
1.索引的种类(六种) 普通索引,唯一索引,全文索引,单列索引,多列索引,空间索引 2.优缺点及注意事项 优点:有了索引,对于记录数量很多的表,可以提高查询速度. 缺点:索引是占用空间的,索引会影响u ...
- Git Server和sourceTree客户端使用说明
一.创建本地仓库 新建一个文件夹,命名为LocalRep,来作为本地仓库. 在终端 cd+拖拽文件夹到终端,打开文件夹在LocalRep目录下操作clone远程仓库到本地,指令如下所示(需根据实际情况 ...