题目大意:
就是给你
n
n
n个节点的树,树上每个节点都有一个权值
w
i
∈
[
l
i
,
r
i
]
w_i\in[l_i,r_i]
wi∈[li,ri],以及相邻
(
u
,
v
)
(u,v)
(u,v)的异或值
w
u
X
O
R
w
v
w_uXORw_v
wuXORwv
问你
w
1...
n
w_{1...n}
w1...n有多少种取值?
解题思路:
-
我们知道如果一个节点的权值定下来的话,那么整颗树的所有点的权值都定下来了!
-
现在我们假设 w 1 ′ = 0 w'_1=0 w1′=0那么我们就可以解出 w 2.... n ′ w'_{2....n} w2....n′我们设这个为初始解
-
如果 w 1 ′ = a w'_1=a w1′=a的话就相当与 w 2... n ′ X O R a w'_{2...n}XORa w2...n′XORa
-
那么就是有 n n n组限制
l i ≤ w i X O R a ≤ r i ∣ i ∈ [ 1 , n ] l_i\leq w_iXORa\leq r_i|i\in[1,n] li≤wiXORa≤ri∣i∈[1,n]
求满足上面式子 a a a的个数
那么
w i X O R l i ≤ a ≤ w i X O R r i ∣ i ∈ [ 1 , n ] w_iXORl_i\leq a \leq w_iXORr_i|i\in[1,n] wiXORli≤a≤wiXORri∣i∈[1,n]
但是根据异或的性质这些区间是不连续的
那么就是求
[ w i ( X O R ) l i , w i ( X O R ) r i ] ∣ i ∈ [ 1 , n ] [w_i(XOR)l_i , w_i(XOR)r_i]|i\in[1,n] [wi(XOR)li,wi(XOR)ri]∣i∈[1,n]
里面连续的区间
然后对这 n n n组区间求交就是答案了!! -
但是如何求呢?
我们知道对于 [ 8 , 15 ] 10 [8,15]_{10} [8,15]10 − > -> −> [ 1000 , 1111 ] 2 [1000,1111]_2 [1000,1111]2
里面除了高位之外下面的低3位的组合是全部的组合!
就是 000 , 001 , 010 , . . . . 110 , 111 000,001,010,....110,111 000,001,010,....110,111都是有的,那么就是你任何一个数异或上这个区间里面的数,你低3位的取值是全部的!那么你只看高位,低3位全部变成0,就是这个区间里面的最小值,然后低3位全是1就是最大值!!
那么这个区间怎么划分呢?
巧了和线段树有关
[
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
]
10
[0,1,2,3,4,5,6,7]_{10}
[0,1,2,3,4,5,6,7]10
[
000
,
001
,
.
.
.
.
,
110
,
111
]
2
[000,001,....,110,111]_2
[000,001,....,110,111]2
那么区间划分除2
[
0
,
1
,
2
,
3
]
[
4
,
5
,
6
,
7
]
[0,1,2,3] [4,5,6,7]
[0,1,2,3][4,5,6,7]
[
000
,
001
,
010
,
011
]
2
[
100
,
101
,
110
,
111
]
2
[000,001,010,011]_2[100,101,110,111]_2
[000,001,010,011]2[100,101,110,111]2这时候就是低2位了!!
每次划分一次低位就减一!!
#include <bits/stdc++.h>
#define mid ((l + r) >> 1)
#define Lson rt << 1, l , mid
#define Rson rt << 1|1, mid + 1, r
#define ms(a,al) memset(a,al,sizeof(a))
#define log2(a) log(a)/log(2)
#define lowbit(x) ((-x) & x)
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define INF 0x3f3f3f3f
#define LLF 0x3f3f3f3f3f3f3f3f
#define f first
#define s second
#define endl '\n'
using namespace std;
const int N = 2e6 + 10, mod = 1e9 + 9;
const int maxn = 500010;
const long double eps = 1e-5;
const int EPS = 500 * 500;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef pair<double,double> PDD;
template<typename T> void read(T &x)
{
x = 0;char ch = getchar();ll f = 1;
while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
template<typename T, typename... Args> void read(T &first, Args& ... args)
{
read(first);
read(args...);
}
int n;
int L[maxn], R[maxn];
vector<PII> G[maxn];
int val[maxn];
vector<PII> vec;
inline void dfs(int u, int fa, int Xor) {
val[u] = Xor;
for(auto it : G[u]) {
int v = it.first, w = it.second;
if(v == fa) continue;
dfs(v,u,Xor^w);
}
}
inline void query(int L, int R, int val, int l, int r, int pos) {
if(L <= l && R >= r) {//把低pos位设置成0
int ql = (l ^ val) & (((1 << 30) - 1) ^ ((1 << pos) - 1));
int qr = ql + (1 << pos) - 1;//设置成1
vec.push_back({ql,qr});
return;
}
if(L <= mid) query(L,R,val,l,mid,pos-1);
if(R > mid) query(L,R,val,mid+1,r,pos-1);
}
inline int slove() {//差分求区间交!!
vector<PII> res;
for(auto it : vec) {
res.push_back({it.first,1});
res.push_back({it.second+1,-1});
}
sort(res.begin(),res.end());
int tag = 0;
int ans = 0;
int last;
for(auto it : res) {
if(tag == n) ans += it.first - last;
tag += it.second;
last = it.first;
}
return ans;
}
int main() {
IOS;
int T;
// cin >> T;
T = 1;
while(T --) {
cin >> n;
for(int i = 1; i <= n; ++ i) cin >> L[i] >> R[i];
for(int i = 1; i <= n - 1; ++ i) {
int u, v , val;
cin >> u >> v >> val;
G[u].push_back({v,val});
G[v].push_back({u,val});
}
dfs(1,-1,0);
for(int i = 1; i <= n; ++ i)
query(L[i],R[i],val[i],0,(1 << 30)-1,30);
cout << slove();
}
}