<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [集訓隊互測 2022] 在路上 題解

      這題的幾個 trick 還是比較重要的。

      題目傳送門:洛谷&QOJ

      下面默認 \(\frac{n}{2}\) 下取整。

      這種詢問樹上三個點的關系的題有一個經典策略是拉出一條鏈來考慮。

      我們不妨先思考樹是一條鏈的情況。
      首先容易用 \(n\) 次詢問找出這條鏈的兩端,具體來講就是先隨便欽定兩個點 \(l,r\),然后詢問其他點 \(u\),把 \(l,r\) 替換成 \(l,r,u\) 中不是 \(ask(l,r,u)\) 的那兩個點。
      然后考慮隨機二分。
      我們在鏈上每次隨機一個點 \(x\),用 \(len\) 次詢問(\(len\) 是當前鏈長)求出它左邊和右邊的點的個數,如果點數均為 \(\frac{n}{2}\),那它就是重心,否則遞歸到大的那一邊去做。
      因為每一次期望刪掉 \(\frac{1}{4}\) 的點,所以總復雜度期望是 \(O(n+\frac{3}{4}n+\frac{9}{16}n+...)=O(n)\)。(差不多 \(4n\) 次詢問,算上開頭那 \(n\) 次剛剛好可以過鏈的部分分)。

      接下來看一般情況。
      因為重心的每個子樹大小不超過 \(\frac{n}{2}\),所以每次隨機兩個點 \(x,y\) 重心在這兩個點的路徑上的概率至少是 \(\frac{1}{2}\)

      證明:假設重心的每棵子樹大小是 \(a_1,a_2,a_3,...,a_k\),那么重心不在 \(x,y\) 路徑上的概率是 \(\frac{\sum_{i=1}^k a_i^2}{n^2}\)
      因為 \(\forall i\in [1,k],a_i \le \frac{n}{2}\),所以 \(k\ge 2\),而由于 \(x^2+y^2\le (x+y)^2\),所以要使分子取到最大值 \(k=2\),即 \(a_1=a_2=\frac{n}{2}\),此時概率是 \(\frac{1}{2}\)

      所以只需要隨機 \(O(1)\) 次就可以找到一條經過重心的鏈。
      我們每次找出隨機的鏈上有可能是重心的點,并 check 它是否真的是重心就可以了。

      假設當前的鏈是 \(x,y\),點集是 \(S\),初始時 \(S\) 是全集,我們用 \(|S|\) 次詢問就可以求出哪些點在鏈上,哪些點掛在 \(x,y\) 下面,哪些點掛在鏈上其他點的下面。
      可能成為重心的點 \(u\) 需要滿足他左邊的點集(不包括自己) \(L\) 和右邊的點集(不包括自己) \(R\) 的大小都 \(\le \frac{n}{2}\)(容易證明一條鏈上這樣的 \(u\) 有且僅有一個),如下圖:

      我們先判掉端點 \(x,y\)\(u\) 的情況,下面只需要考慮 \(u\) 是鏈上其他點的情況。
      如果我們隨機一個 \(u\),那么可以用 \(|S|\) 次詢問求出一個點屬于 \(L,R\)\(u\) 子樹中的哪個,具體來講對于一個點 \(v\)

      1. 如果 \(ask(x,u,v)\ne u\),那 \(v\) 就屬于 \(L\)
      2. 否則如果 \(ask(y,u,v)\ne u\),那 \(v\) 就屬于 \(R\)
      3. 其他情況 \(v\) 就屬于 \(u\) 子樹。

      如果 \(L,R\) 的大小都不超過 \(\frac{n}{2}\),那 \(u\) 就是要找的點,否則扔掉小的那部分遞歸去做。(\(u\) 子樹會被保留)
      注意: 比如說 \(R> \frac{n}{2}\),那么會扔掉 \(L\),但是雖然之后 \(L\) 內的點不再屬于 \(S\),但是他們仍然要考慮到之后的子問題的 \(L\) 中。

      但是因為此時樹不再是一條鏈,所以每次隨機二分,并不能期望刪掉 \(\frac{1}{4}\) 的點(比如這條鏈上某一邊有個點的子樹特別大,但是你隨到的點一直在另一邊),復雜度和詢問次數都是錯的。
      于是我們考慮帶權二分,原先每個點被隨到的概率都是一樣的,現在我們希望一個子樹大小是 \(siz\) 的點被隨到的概率是 \(\frac{siz}{|S|}\)
      但是現在我們并不知道樹的結構,也就不知道每個點的 \(siz\),好像沒法帶權二分。
      但是如果我們在 \(S\) 中隨機一個點 \(v\),那么這個點是鏈上 \(u\) 子樹內的點的概率正好就是 \(\frac{siz}{S}\)
      所以我們只需要每次隨機一個點 \(v\) 并找到他所對應的鏈上的點就完成了帶權二分的過程。
      要找到 \(v\) 所對應的點 \(u\) 可以先假定 \(u=x\) 然后遍歷鏈上的所有點,當遍歷到一個點 \(i\) 時如果 \(ask(v,u,i)=i\) 就令 \(u=i\)

      最后剩下的問題就是怎么 check 一個點 \(u\) 是不是重心。
      如果 \(u\) 不是重心,那么必然有一個子樹的大小 \(>\frac{n}{2}\),所以我們可以考慮用摩爾投票的方法求出這個最大的子樹。
      回顧如何用摩爾投票求序列絕對眾數:設 \(x\) 是絕對眾數,并維護一個變量 \(cnt\),初始時令 \(x\gets a_1,cnt\gets 1\),對于序列中的其他數 \(y\),如果 \(x=y\) 就令 \(cnt\gets cnt+1\),否則令 \(cnt\gets cnt-1\),如果此時 \(cnt\) 變成負數就令 \(x\gets y,cnt\gets 1\),如果序列存在絕對眾數那最終的 \(x\) 就是絕對眾數。
      同樣的,我們維護一個 \(x\) 表示最大的子樹中的點,同時維護一個變量 \(cnt\)。初始 \(x\) 任取一個點,\(cnt=1\),當遍歷到一個點 \(y\) 時,如果 \(ask(x,y,u)\ne u\) 意味著 \(x,y\) 在同一個子樹,令 \(cnt\gets cnt+1\),否則同理。
      最后我們再用 \(n\) 次詢問去求出 \(x\) 所在子樹的真實大小看一下是否 \(>\frac{n}{2}\) 即可。

      詢問次數是線性的,常數系數不知道。

      code
      下面這份代碼是以洛谷的交互庫為標準的。

      #include<bits/stdc++.h>
      #define PII pair<int,int>
      #define PIII pair<int,pair<int,int> > 
      #define fi first
      #define se second 
      #define eb emplace_back
      #define Debug puts("----------------")
      using namespace std;
      extern "C"  int ask(int x,int y,int z);
      int query(int x,int y,int z){
      	if(x==y) return x;
      	if(x==z) return x;
      	if(y==z) return y;
      	return ask(x,y,z);
      }
      mt19937 rnd(20100307);
      int n;
      bool flag[50005],in_subx[50005],in_suby[50005];
      int solve(int x,int y,int sizL,int sizR,vector<int> node){
      	vector<int> list,other;  
      	int siz_x=0,siz_y=0;
      	if(n==49999){
      		siz_x=siz_y=1;
      		for(int i:node){
      			flag[i]=true;
      			if(i==x) in_subx[i]=true; else in_subx[i]=false;
      			if(i==y) in_suby[i]=true; else in_suby[i]=false;
      			if(i!=x&&i!=y) other.eb(i);		
      		}	
      	}
      	else{
      		for(int i:node){
      			int u=query(x,y,i);
      			if(u==x) siz_x++,in_subx[i]=true; else in_subx[i]=false;
      			if(u==y) siz_y++,in_suby[i]=true; else in_suby[i]=false;
      			if(u==i) list.eb(i),flag[i]=true;
      			else flag[i]=false;
      			if(!in_subx[i]&&!in_suby[i]) other.eb(i);
      		} 
      	}
      	
      	if(node.size()-siz_x+sizR<=n/2) return x;   //排除 x,y 是重心的情況 
      	if(node.size()-siz_y+sizL<=n/2) return y;
      	
      	int v=other[rnd()%(other.size())],u;
      	if(flag[v]) u=v;
      	else{
      		u=x;
      		for(int i:list){
      			if(i==x) continue;
      			if(query(u,i,v)==i) u=i;	
      		}
      	}
      	
      	vector<int> L,R,subtree;
      	for(int i:node){
      		if(in_subx[i]){
      			L.eb(i);
      			continue;
      		}
      		if(in_suby[i]){
      			R.eb(i);
      			continue;
      		}
      		if(n==49999){
      			if(i==u) subtree.eb(i);
      			else{
      				int z=query(x,u,i);
      				if(z==u) R.eb(i);
      				else L.eb(i); 
      			}
      			continue;
      		}
      		int z=query(x,u,i);
      		if(z==u){
      			if(query(u,y,i)==u) subtree.eb(i);
      			else R.eb(i);
      		}
      		else L.eb(i);
      	}
      	if(L.size()+sizL>n/2){
      		for(int i:subtree) L.eb(i);
      		return solve(x,u,sizL,sizR+R.size(),L);
      	}
      	else if(R.size()+sizR>n/2){
      		for(int i:subtree) R.eb(i);
      		return solve(u,y,sizL+L.size(),sizR,R);		
      	}
      	return u;
      }
      bool check(int u){
      	int cnt=1,x=1,siz=0;
      	if(x==u) x++;
      	for(int y=x+1;y<=n;y++){
      		if(y==u) continue;
      		if(query(x,y,u)!=u) cnt++;
      		else{
      			cnt--;
      			if(cnt<0) x=y,cnt=1;
      		}
      	}
      	for(int y=1;y<=n;y++){
      		if(y==u) continue;
      		if(query(x,y,u)!=u) siz++;
      	}
      	return siz<=n/2;
      }
      extern "C"  int centroid(int id,int N,int M){
      	if(N==3) return ask(1,2,3);
      	map<PII,bool> mp;
      	n=N;
      	vector<int> all(n);
      	for(int i=1;i<=n;i++) all[i-1]=i;
      	if(n==49999){  //注意鏈的情況的特殊數據范圍 
      		int l=1,r=2;
      		for(int i=3;i<=n;i++){
      			int u=query(l,r,i);
      			if(u==l) l=i;
      			else if(u==r) r=i;
      		}	
      		return solve(l,r,0,0,all);
      	} 
      	while(true){
      		int x=rnd()%n+1,y=rnd()%n+1;
      		while(mp[{x,y}]||x==y) x=rnd()%n+1,y=rnd()%n+1;
      		mp[{x,y}]=true;
      		int u=solve(x,y,0,0,all);
      		if(check(u)) return u;
      	}
      }
      

      弱弱地問一句,有沒有人會嚴格證明這個帶權二分的期望復雜度,寫的時候突然發現自己不是很會證。

      posted @ 2025-05-09 16:02  Green&White  閱讀(25)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久热这里只国产精品视频| 安仁县| 中文字幕一区二区人妻电影| 日本一本正道综合久久dvd| 亚洲欧美激情在线一区| 熟妇人妻系列aⅴ无码专区友真希| 国产在线精彩自拍视频| 男女性杂交内射女bbwxz| 強壮公弄得我次次高潮A片| 性欧美vr高清极品| 久久99九九精品久久久久蜜桃| 精品午夜福利短视频一区| 午夜免费福利小电影| 欧美性猛交xxxx免费看| 高清偷拍一区二区三区| 国产中文字幕精品在线| 国产精品无码a∨麻豆| 伊人色综合一区二区三区| 国产精品中文字幕久久| 中文人妻熟妇乱又伦精品| 国产成人自拍小视频在线| 国产一区二区三区内射高清| 在线看国产精品自拍内射| 男女一边摸一边做爽爽| 国产精品一区二区久久毛片| 国产麻豆成人传媒免费观看| 国产午精品午夜福利757视频播放| 亚洲中文无码av永久不收费| 日韩有码中文在线观看| 国产一区二区三区小说| 齐河县| 中国女人高潮hd| 亚洲色大成网站www看下面| 花式道具play高h文调教| 在线a人片免费观看| 黄网站色视频免费观看| 亚洲一精品一区二区三区| 深夜释放自己在线观看| 久久精品第九区免费观看| 97在线碰| 午夜三级成人在线观看|