日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

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

發(fā)布時(shí)間:2023/12/4 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2021牛客暑期多校训练营4 E - Tree Xor 线段树 + 拆分区间 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

傳送門

文章目錄

  • 題意:
  • 思路:

題意:

給你一棵樹(shù),每個(gè)點(diǎn)原本都有一個(gè)權(quán)值wiw_iwi?,但是你只知道相鄰兩個(gè)點(diǎn)之間的wu⊕wvw_u\oplus w_vwu?wv?,問(wèn)你有多少種w1,2,...,nw_{1,2,...,n}w1,2,...,n?
n≤1e5,wi<230n\le1e5,w_i<2^{30}n1e5,wi?<230

思路:

顯然我們?nèi)绻_定了一個(gè)點(diǎn)的權(quán)值,那么其他的點(diǎn)都就確定了。
更具體的是,我們可以求出111到其他點(diǎn)之間的w1⊕wxw_1\oplus w_xw1?wx?,其中我們可以假設(shè)w1=0w_1=0w1?=0,那么當(dāng)給w1⊕aw_1\oplus aw1?a時(shí),就相當(dāng)于將其他w2,3,...,n⊕aw_{2,3,...,n}\oplus aw2,3,...,n?a,所以我們問(wèn)題就轉(zhuǎn)換成了對(duì)于每個(gè)區(qū)間求合法的aaa使得li≤wi⊕a≤ril_i\le w_i\oplus a\le r_ili?wi?ari?,轉(zhuǎn)換一下就是wi⊕[li,ri]w_i\oplus [l_i,r_i]wi?[li?,ri?]的合法區(qū)間。這個(gè)區(qū)間肯定不是連續(xù)的,所以考慮將其拆分成若干區(qū)間。
由于拆分的區(qū)間肯定不能很多,所以考慮用二進(jìn)制來(lái)拆分這個(gè)區(qū)間。考慮這樣一種形式的二進(jìn)制區(qū)間[xxxx0000,xxxx1111][xxxx0000,xxxx1111][xxxx0000,xxxx1111],其中xxx表示可以是任意數(shù),但是兩個(gè)的xxx對(duì)應(yīng)位置必須相同。這樣的區(qū)間滿足其異或上wiw_iwi?仍是一段連續(xù)的區(qū)間。我們驚奇的發(fā)現(xiàn),這個(gè)區(qū)間后半部分不正是線段樹(shù)的每段區(qū)間嗎?所以考慮建一棵[0,230?1][0,2^{30}-1][0,230?1]的線段樹(shù),將這個(gè)區(qū)間插入,可知最多能被分成lognlognlogn段區(qū)間。當(dāng)這個(gè)區(qū)間被完全包含的時(shí)候,我們打一個(gè)懶標(biāo)記即可。
查詢的時(shí)候如果懶標(biāo)記=n=n=n的時(shí)候,就直接返回區(qū)間長(zhǎng)度即可。

// 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("Ofast,no-stack-protector,unroll-loops,fast-math") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native") //#pragma GCC optimize(2) #include<cstdio> #include<iostream> #include<string> #include<cstring> #include<map> #include<cmath> #include<cctype> #include<vector> #include<set> #include<queue> #include<algorithm> #include<sstream> #include<ctime> #include<cstdlib> #include<random> #include<cassert> #define X first #define Y second #define L (u<<1) #define R (u<<1|1) #define pb push_back #define mk make_pair #define Mid ((tr[u].l+tr[u].r)>>1) #define Len(u) (tr[u].r-tr[u].l+1) #define random(a,b) ((a)+rand()%((b)-(a)+1)) #define db puts("---") using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); } //void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); } //void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> PII;const int N=5000010,mod=1e9+7,INF=0x3f3f3f3f; const double eps=1e-6;int n,w[N],p[N]; int l[N],r[N],idx; struct Node {int l,r;int cnt,lazy; }tr[N<<2]; vector<PII>v[N];void dfs(int u,int fa) {for(auto x:v[u]) {if(x.X==fa) continue;w[x.X]=w[u]^x.Y;dfs(x.X,u);} }int newnode() {int u=++idx;tr[u].l=tr[u].r=0;tr[u].cnt=tr[u].lazy=0;return u; }void insert(int &u,int l,int r,int ql,int qr,int w,int dep) {if(!u) u=newnode();int nl=(l^w)&(((1<<30)-1)^((1<<(dep+1))-1));int nr=(l^w)|((1<<(dep+1))-1);if(nl>=ql&&nr<=qr) {tr[u].lazy++;tr[u].cnt++;return;}if(tr[u].cnt) {if(!tr[u].l) tr[u].l=newnode();if(!tr[u].r) tr[u].r=newnode();tr[tr[u].l].cnt+=tr[u].cnt; tr[tr[u].r].cnt+=tr[u].cnt;tr[u].cnt=0;}int mid=(l+r)>>1;int ll=(l^w)&(((1<<30)-1)^((1<<(dep))-1)),lr=(l^w)|((1<<(dep))-1);int rl=(r^w)&(((1<<30)-1)^((1<<(dep))-1)),rr=(r^w)|((1<<(dep))-1);if(w>>dep&1) {if(ql<=rr) insert(tr[u].r,mid+1,r,ql,qr,w,dep-1);if(qr>=ll) insert(tr[u].l,l,mid,ql,qr,w,dep-1);} else {if(ql<=lr) insert(tr[u].l,l,mid,ql,qr,w,dep-1);if(qr>=rl) insert(tr[u].r,mid+1,r,ql,qr,w,dep-1);} }int query(int u,int l,int r) {if(!u) return 0;if(tr[u].cnt==n) return r-l+1;if(tr[u].cnt) {if(tr[u].l) tr[tr[u].l].cnt+=tr[u].cnt;if(tr[u].r) tr[tr[u].r].cnt+=tr[u].cnt;tr[u].cnt=0;}int ans=0,mid=(l+r)>>1;ans+=query(tr[u].l,l,mid);ans+=query(tr[u].r,mid+1,r);return ans; }int main() { // ios::sync_with_stdio(false); // cin.tie(0);scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d%d",&l[i],&r[i]);for(int i=1;i<=n-1;i++) {int a,b,c; scanf("%d%d%d",&a,&b,&c);v[a].pb({b,c}); v[b].pb({a,c});}dfs(1,0); int rt=newnode();int limit=(1<<30)-1;for(int i=1;i<=n;i++) {insert(rt,0,limit,l[i],r[i],w[i],29);}printf("%d\n",query(1,0,limit));return 0; } /**/

總結(jié)

以上是生活随笔為你收集整理的2021牛客暑期多校训练营4 E - Tree Xor 线段树 + 拆分区间的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。