题目链接:点击查看

题目大意:给出一棵 nnn 个点组成的树,每个点权的取值范围是 [li,ri][l_i,r_i][li​,ri​],每条边权代表的是两点的异或值,现在问这棵树有多少种有效赋值

题目分析:假设点 111 为基准点,找到点 111 到 nnn 个点的路径上的异或和记为 wiw_iwi​,那么问题转换为了,点 111 有多少种可行的取值 xxx,需要同时满足 nnn 个不等式:li≤(wi⊕x)≤ril_i\le (w_i\oplus x)\le r_ili​≤(wi​⊕x)≤ri​

考虑 wi⊕[li,ri]w_i \oplus [l_i,r_i]wi​⊕[li​,ri​] 后的新区间,打表发现并不具有连续性。但是这里有一个异或的性质:

我们可以利用 [0,230−1][0,2^{30}-1][0,230−1] 的线段树, 把 [Li,Ri][L_i , R_i][Li​,Ri​] 分成 O(logW)O(logW)O(logW)
个连续的区间,且每个区间的形式是 : k...30k...30k...30 位相同,0...k−10...k-10...k−1 位是 000 到 2k−12^k-12k−1,这样的区间异或上
wiw_iwi​ 后仍然还是一个区间

所以可以利用上述性质将 wi⊕[li,ri]w_i \oplus [l_i,r_i]wi​⊕[li​,ri​] 拆成 O(logW)O(logW)O(logW) 个新区间,放到线段树上,最后统计一下 nnn 个新区间的交集就是答案了

代码:

// Problem: Tree Xor
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/11255/E
// Memory Limit: 524288 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) (x&-x)
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f;
}
template<typename T>
inline void write(T x)
{if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e5+100;
const int limit=(1<<30)-1;
int l[N],r[N],w[N],n;
vector<pair<int,int>>node[N];
struct Node {int l,r,lazy;
}tree[N*4*20];
int tot=0;
int newnode() {tot++;tree[tot].l=tree[tot].r=tree[tot].lazy;return tot;
}
int get_l(int x,int dep) {//return xxxxx|00000return x&(limit^((1<<dep)-1));
}
int get_r(int x,int dep) {//return xxxxx|11111return x|((1<<dep)-1);
}
int inter(int l1,int r1,int l2,int r2) {return max(l1,l2)<=min(r1,r2);
}
void insert(int& k,int l,int r,int x,int y,int w,int dep) {if(!k) {k=newnode();}if(get_l(l^w,dep)>=x&&get_r(l^w,dep)<=y) {tree[k].lazy++;return;}if(tree[k].lazy) {int lz=tree[k].lazy;tree[k].lazy=0;if(!tree[k].l) {tree[k].l=newnode();}if(!tree[k].r) {tree[k].r=newnode();}tree[tree[k].l].lazy+=lz;tree[tree[k].r].lazy+=lz;}int mid=(l+r)>>1;if(inter(x,y,get_l(l^w,dep-1),get_r(l^w,dep-1))) {insert(tree[k].l,l,mid,x,y,w,dep-1);}if(inter(x,y,get_l((mid+1)^w,dep-1),get_r((mid+1)^w,dep-1))) {insert(tree[k].r,mid+1,r,x,y,w,dep-1);}
}
int query(int k,int l,int r) {if(!k) {return 0;}if(tree[k].lazy==n) {return r-l+1;}if(tree[k].lazy) {int lz=tree[k].lazy;tree[k].lazy=0;if(tree[k].l) {tree[tree[k].l].lazy+=lz;}if(tree[k].r) {tree[tree[k].r].lazy+=lz;}}int mid=(l+r)>>1;return query(tree[k].l,l,mid)+query(tree[k].r,mid+1,r);
}
void dfs(int u,int fa,int sum) {w[u]=sum;for(auto it:node[u]) {int v=it.first,w=it.second;if(v==fa) {continue;}dfs(v,u,sum^w);}
}
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);read(n);for(int i=1;i<=n;i++) {read(l[i]),read(r[i]);}for(int i=1;i<n;i++) {int u,v,w;read(u),read(v),read(w);node[u].push_back({v,w});node[v].push_back({u,w});}dfs(1,-1,0);int rt=0;for(int i=1;i<=n;i++) {insert(rt,0,limit,l[i],r[i],w[i],30);}cout<<query(rt,0,limit)<<endl;return 0;
}

2021牛客多校4 - Tree Xor(线段树+异或区间拆分)相关推荐

  1. 牛客多校6 - Josephus Transform(线段树求k-约瑟夫环+置换群的幂)

    题目链接:点击查看 题目大意:给出一个长度为 n 的排列,初始时为 1 , 2 , 3 ... n - 1 , n,现在有 m 次操作,每次操作表示为 ( k , x ) ,即进行 x 次 k-约瑟夫 ...

  2. 2019 牛客多校 C Governing sand 线段树

    链接:https://ac.nowcoder.com/acm/contest/887/C 来源:牛客网 Governing sand 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 6 ...

  3. 牛客多校8 - All-Star Game(线段树分治+并查集按秩合并的撤销操作)

    题目链接:点击查看 题目大意:有 n 个球员和 m 个球迷,一个球员可能是多个球迷的粉丝,需要选择最少的球员进行比赛,使得所有的球迷都愿意观看(对于每个球迷来说,都有至少一个其喜欢的球员入选比赛) 对 ...

  4. 2021牛客多校#4 E-Tree Xor

    文章目录 题目链接 题目大意 题解 参考代码 题目链接 传送门 题目大意 给定一棵n(1≤n≤105)n(1 \leq n \leq 10^5)n(1≤n≤105)的节点的树,第iii个节点的权值为W ...

  5. LCS(2021牛客多校4)

    LCS(2021牛客多校4) 题意: 让你构造三个字符串s1,s2,s3,长度均为n,要求LCS(s1,s2)=a,LCS(s2,s3)=b,LCS(s1,s3)=c 题解: 先考虑三个串互相LCS为 ...

  6. 【2021牛客多校2】F-Girlfriend 计算几何

    2021牛客多校2-F F-Girlfriend 题目大意 给出四个点 A , B , C , D A, B, C, D A,B,C,D 另有两点 P 1 , P 2 P_1, P_2 P1​,P2​ ...

  7. 2021牛客多校7 - xay loves monotonicity(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数字序列 aaa 和 010101 序列 bbb,需要执行 mmm 次操作,每次操作分为如下三种类型: 1 x y:修改 a[x]=ya[x]= ...

  8. 【多校训练】2021牛客多校第一场

    [前言] 组队训练的第一场比赛,感觉这场出题十分阴间,后面几个乱搞题根本不会.jpg 赛时只过了5题,rk123,学校参加5/8. A. Alice and Bob [题意] 两人博弈,每次一个人从一 ...

  9. 2021牛客暑期多校训练营4 E - Tree Xor 线段树 + 拆分区间

    传送门 文章目录 题意: 思路: 题意: 给你一棵树,每个点原本都有一个权值wiw_iwi​,但是你只知道相邻两个点之间的wu⊕wvw_u\oplus w_vwu​⊕wv​,问你有多少种w1,2,.. ...

最新文章

  1. Failed to instantiate one or more classes
  2. python考证书-python能考证么
  3. 高并发编程基础(java.util.concurrent包常见类基础)
  4. android frida 检测_frida测试方法整理
  5. 【C#每日一贴】ArrayList 转换成byte数组
  6. 用pythone画棵圣诞树,祝大家圣诞快乐
  7. 《Imperfect C++中文版》——1.3 运行期契约:前置条件、后置条件和不变式
  8. java tcp怎么拆包_Java网络编程基础之TCP粘包拆包
  9. 一文搞懂List 、ListObject、List?的区别以及? extends T与? super T的区别
  10. Ubuntu 16.04安装Caffe的记录及FCN官方代码的配置
  11. 【HTTP请求】、详解
  12. learning opencv3: 一:overview 打开自己的视频文件加上暂停快进按钮
  13. 矩阵分析与应用(5)
  14. python用matplotlib或boxplot作图的时候,中文标注无法正常显示,乱码为小方框的解决办法
  15. HTML5 标签汇总
  16. 微信公众号迁移公证办理流程
  17. ConfigUtil.class.getResource
  18. 2017-08-25阿里校招笔试题---菜鸟仓库
  19. 高防是互联网攻击宠儿的救星?你选对了吗?
  20. Cairo-基本概念

热门文章

  1. linux 源码 在线浏览,Linux下实现文档在线浏览
  2. redis内存行数据库细节
  3. Condition.signal
  4. 手写自己的MyBatis框架-支持插件
  5. 手写自己的MyBatis框架-V2.0配置文件
  6. Nacos配置中心-命名空间与配置分组
  7. RocketMQ的Consumer详解之重复消息的解决方案
  8. HDFS的namenode和datanode
  9. 再次强调事件绑定中this的坑
  10. MyBatis增删改对二级缓存的影响