2021牛客暑期多校训练营4 Tree Xor (区间异或上一个数+区间求交)
Posted 昵称很长很长真是太好了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营4 Tree Xor (区间异或上一个数+区间求交)相关的知识,希望对你有一定的参考价值。
题解:
首先我们可以发现,只要确定了一个值,那么树上其他的值也可以确定下来了,但是显然,遍历一棵树的时间复杂度为O(n),如果枚举+暴力判断的话时间复杂度
O
(
1
e
9
∗
n
)
O(1e9*n)
O(1e9∗n)。
看了大佬的题解。
首先可以假设
a
[
1
]
=
0
a[1]=0
a[1]=0,然后求出其他的点分别为
a
[
i
]
a[i]
a[i]
假设我们把
a
[
1
]
a[1]
a[1]变成
x
x
x,那么其他的点也都会被异或上一个
x
x
x。
假设
l
[
1
]
<
0
⊕
x
<
r
[
1
]
l[1]<0 \\oplus x<r[1]
l[1]<0⊕x<r[1]
那么
l
[
1
]
<
a
[
i
]
⊕
x
<
r
[
1
]
l[1]<a[i] \\oplus x<r[1]
l[1]<a[i]⊕x<r[1]
也就是
l
[
1
]
⊕
x
<
a
[
i
]
<
r
[
1
]
⊕
x
l[1]\\oplus x<a[i]<r[1]\\oplus x
l[1]⊕x<a[i]<r[1]⊕x
然后对n个不等式求一个交集即可。
等等…
区间异或x后好像不是连续的…
看了大佬们的题解才明白该如何操作。
有些区间是可以(感觉不好描述)
看这位大佬对其的解释:https://blog.csdn.net/qq_45874328/article/details/119175535
处理完的区间我们可以存到一个vector中,然后求区间交集即可
类似于差分的求法
对每个区间的左端点为l,右端点为r,拆分成{l,1} {r,-1},放进数组中,然后按照第一维进行排序。
排完序后进行遍历,设一个变量为cnt=0,每次加上i.second,若cnt=n时(n为区间个数)计算当前为n的区间长度即可。
#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include<bits/stdc++.h>
#define int long long
#define endl '\\n'
using namespace std;
const int maxn=5e5+10;
const int MAX=(1<<30)-1;
pair<int,int> pp[maxn];
vector<pair<int,int> > edge[maxn];
vector<pair<int,int> > v;
void query(int start,int ends,int l,int r,int val){
if(l<=start&&ends<=r){
int ansl=(start^val)&(((1<<30)-1)-(ends-start));
int ansr=ansl+(ends-start);
v.push_back({ansl,1});
v.push_back({ansr+1,-1});
return ;
}
int mid=(start+ends)>>1;
if(l<=mid) query(start,mid,l,r,val);
if(mid<r) query(mid+1,ends,l,r,val);
}
void dfs(int x,int fa,int val){
query(0,MAX,pp[x].first,pp[x].second,val);
for(auto i:edge[x]){
if(i.first==fa) continue;
dfs(i.first,x,i.second^val);
}
}
int ans;
int n;
void sol(){
sort(v.begin(),v.end());
int cnt=0;
for(int i=0;i<v.size();i++){
cnt+=v[i].second;
if(cnt==n){
if(i!=v.size()) ans+=v[i+1].first-v[i].first;
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++){
cin>>pp[i].first>>pp[i].second;
}
for(int i=1;i<n;i++){
int x,y,z;
cin>>x>>y>>z;
edge[x].push_back({y,z});
edge[y].push_back({x,z});
}
dfs(1,0,0);
sol();
cout<<ans<<endl;
}
以上是关于2021牛客暑期多校训练营4 Tree Xor (区间异或上一个数+区间求交)的主要内容,如果未能解决你的问题,请参考以下文章
2021牛客暑期多校训练营4 Tree Xor (区间异或上一个数+区间求交)