2021牛客多校4 - Tree Xor(线段树+异或区间拆分)
题目链接:点击查看
题目大意:给出一棵 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(线段树+异或区间拆分)相关推荐
- 牛客多校6 - Josephus Transform(线段树求k-约瑟夫环+置换群的幂)
题目链接:点击查看 题目大意:给出一个长度为 n 的排列,初始时为 1 , 2 , 3 ... n - 1 , n,现在有 m 次操作,每次操作表示为 ( k , x ) ,即进行 x 次 k-约瑟夫 ...
- 2019 牛客多校 C Governing sand 线段树
链接:https://ac.nowcoder.com/acm/contest/887/C 来源:牛客网 Governing sand 时间限制:C/C++ 3秒,其他语言6秒 空间限制:C/C++ 6 ...
- 牛客多校8 - All-Star Game(线段树分治+并查集按秩合并的撤销操作)
题目链接:点击查看 题目大意:有 n 个球员和 m 个球迷,一个球员可能是多个球迷的粉丝,需要选择最少的球员进行比赛,使得所有的球迷都愿意观看(对于每个球迷来说,都有至少一个其喜欢的球员入选比赛) 对 ...
- 2021牛客多校#4 E-Tree Xor
文章目录 题目链接 题目大意 题解 参考代码 题目链接 传送门 题目大意 给定一棵n(1≤n≤105)n(1 \leq n \leq 10^5)n(1≤n≤105)的节点的树,第iii个节点的权值为W ...
- LCS(2021牛客多校4)
LCS(2021牛客多校4) 题意: 让你构造三个字符串s1,s2,s3,长度均为n,要求LCS(s1,s2)=a,LCS(s2,s3)=b,LCS(s1,s3)=c 题解: 先考虑三个串互相LCS为 ...
- 【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 ...
- 2021牛客多校7 - xay loves monotonicity(线段树区间合并)
题目链接:点击查看 题目大意:给出一个长度为 nnn 的数字序列 aaa 和 010101 序列 bbb,需要执行 mmm 次操作,每次操作分为如下三种类型: 1 x y:修改 a[x]=ya[x]= ...
- 【多校训练】2021牛客多校第一场
[前言] 组队训练的第一场比赛,感觉这场出题十分阴间,后面几个乱搞题根本不会.jpg 赛时只过了5题,rk123,学校参加5/8. A. Alice and Bob [题意] 两人博弈,每次一个人从一 ...
- 2021牛客暑期多校训练营4 E - Tree Xor 线段树 + 拆分区间
传送门 文章目录 题意: 思路: 题意: 给你一棵树,每个点原本都有一个权值wiw_iwi,但是你只知道相邻两个点之间的wu⊕wvw_u\oplus w_vwu⊕wv,问你有多少种w1,2,.. ...
最新文章
- Failed to instantiate one or more classes
- python考证书-python能考证么
- 高并发编程基础(java.util.concurrent包常见类基础)
- android frida 检测_frida测试方法整理
- 【C#每日一贴】ArrayList 转换成byte数组
- 用pythone画棵圣诞树,祝大家圣诞快乐
- 《Imperfect C++中文版》——1.3 运行期契约:前置条件、后置条件和不变式
- java tcp怎么拆包_Java网络编程基础之TCP粘包拆包
- 一文搞懂List 、ListObject、List?的区别以及? extends T与? super T的区别
- Ubuntu 16.04安装Caffe的记录及FCN官方代码的配置
- 【HTTP请求】、详解
- learning opencv3: 一:overview 打开自己的视频文件加上暂停快进按钮
- 矩阵分析与应用(5)
- python用matplotlib或boxplot作图的时候,中文标注无法正常显示,乱码为小方框的解决办法
- HTML5 标签汇总
- 微信公众号迁移公证办理流程
- ConfigUtil.class.getResource
- 2017-08-25阿里校招笔试题---菜鸟仓库
- 高防是互联网攻击宠儿的救星?你选对了吗?
- Cairo-基本概念