HDU5589 Tree

题意:

给出一棵\(N\)个点的树,每条边有边权,每次询问下标为\([L,R]\)区间内的点能选出多少点对,点对之间的路径上的边权异或和大于\(M\)

题解:

对于两点\(u,v\)之间的路径上的边权的异或和,可以转化为根到点\(u\)的路径上异或和与根到点\(v\)的路径上异或和的异或和,所以可以与处理出根到各个点的路径边权异或和

接下来就变成了一个序列上的问题了,每次询问区间\([L,R]\)之间的点有多少对的异或和大于\(M\)

然后就可以用莫队来处理,为了能快速加值和删值还有查询,而且是异或的操作,这里选择用\(01\)字典树来做

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 5e4+7;
typedef long long int LL;
int n,m,q,w[MAXN];
LL ret[MAXN],ans;
struct Trie{
int tot,ch[MAXN<<4][2],cnt[MAXN<<4];
void clear(){
for(int i = 1; i <= tot; i++) ch[i][0] = ch[i][1] = cnt[i] = 0;
tot = 1;
}
void insert(int x, int now = 1){
for(int i = 19; i >= 0; i--){
if(!ch[now][(x>>i)&1]) ch[now][(x>>i)&1] = ++tot;
cnt[now = ch[now][(x>>i)&1]]++;
}
}
void erase(int x, int now = 1){
for(int i = 19; i >= 0; i--) cnt[now = ch[now][(x>>i)&1]]--;
}
int query(int x){
int ret = 0, now = 1;
for(int i = 19; i >= 0 and now; i--){
int bm = ((m>>i)&1);
int bx = ((x>>i)&1);
if(!bm) ret += cnt[ch[now][bx^1]], now = ch[now][bx];
else now = ch[now][bx^1];
}
return ret;
}
}trie;
struct Query{ int l, r, id; } Q[MAXN];
vector<pair<int,int>> G[MAXN];
void dfs(int u, int par){
for(auto e : G[u]) if(e.first!=par){
w[e.first] = w[u] ^ e.second;
dfs(e.first,u);
}
}
void inc(int x){
ans += trie.query(x);
trie.insert(x);
}
void dec(int x){
trie.erase(x);
ans -= trie.query(x);
}
void solve(){
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 1; i < n; i++){
int u, v, wt;
scanf("%d %d %d",&u,&v,&wt);
G[u].push_back(make_pair(v,wt)); G[v].push_back(make_pair(u,wt));
}
dfs(1,0); trie.clear();
for(int i = 1; i <= q; i++) scanf("%d %d",&Q[i].l,&Q[i].r), Q[i].id = i;
int sqt = sqrt(n);
sort(Q+1,Q+1+q,[&sqt](const Query &lhs, const Query &rhs){
return lhs.l / sqt == rhs.l / sqt ? lhs.r < rhs.r : lhs.l / sqt < rhs.l / sqt;
});
int L = 1, R = 0;
ans = 0;
for(int i = 1; i <= q; i++){
while(L>Q[i].l) inc(w[--L]);
while(R<Q[i].r) inc(w[++R]);
while(L<Q[i].l) dec(w[L++]);
while(R>Q[i].r) dec(w[R--]);
ret[Q[i].id] = ans;
}
for(int i = 1; i <= q; i++) printf("%I64d\n",ret[i]);
}
int main(){
while(scanf("%d %d %d",&n,&m,&q)!=EOF) solve();
return 0;
}

最新文章

  1. SOA服务类项目开发模式
  2. 数据挖掘算法(一)C4.5
  3. javaweb学习总结(二十九)——EL表达式
  4. Android NDK 构建 以及一些错误
  5. DiskGenius的 “终止位置参数溢出”错误解决方法。
  6. Java中的事务——JDBC事务和JTA事务
  7. android的版本控制
  8. POJ 2396 Budget 有上下界的网络流
  9. Swift中实现ruby中字符串乘法倍增的功能
  10. 手动清除mac的广告弹框病毒 MacOSDefender
  11. Google Apps的单点登录-谷歌使用的单点登录
  12. 【FFmpeg】ffplay播放rtsp视频流花屏问题 (转)
  13. 在dbgrideh中允许选择多行,如何知道哪些行被选中
  14. python: numpy--函数 shape用法
  15. php让页面记住表单提交后的信息方法
  16. codeforces9D How many trees?
  17. HDU 2143 Can you find it?(基础二分)
  18. android gallery 自定义边框+幻灯片效果
  19. hdoj 1026 Ignatius and the Princess I 最小步数,并且保存路径
  20. Zabbix分布式监控

热门文章

  1. js如何替换字符串中匹配到多处中某一指定节点?
  2. Linux SSH , SCP 建立信任关系(免密传输)
  3. 基于Docker搭建Hadoop+Hive
  4. Java高并发与多线程(二)-----线程的实现方式
  5. SpringBoot快速掌握(1):核心技术
  6. Navicat linux 官方最新版安装破解
  7. OLED的波形曲线、进度条、图片显示(STM32 HAL库 模拟SPI通信 5线OLED屏幕)详细篇
  8. Docker容器日志清理方案
  9. 理想的DevOp流程怎么做?看看Slack的代码部署实践 原创 Michael Deng 高可用架构 今天
  10. (Sql Server)Soundex语音算法