沒有用\(o(n)\)的做法,是\(o(nlogn)\)的線段樹維護直徑 (o(n)的需要維護的資訊我覺得又多又亂)
將樹的節點按\(dfs\)序建線段樹維護聯通塊的直徑
列舉每一條邊,檢視刪掉它之後,剩餘的兩個聯通塊合併後的直徑 所能取到的 最小的最大值
即 最小的 len=max \) + \(\frac\) +1}
\(l_1和l_2\) 是兩個聯通塊的直徑。
記錄\(len\)的最小值及其個數,以及此時的要刪的邊的編號。
對於找端點,選一條要刪的邊,輸出其端點,然後分別\(dfs\)找到兩個聯通塊直徑的中點輸出即可
code
#include #include #include #include #include using namespace std;
char buf[1<<20],*p1,*p2;
#define l (rt*2)
#define r (rt*2+1)
#define rint register int
#define gc() (p1==p2?(p2=buf+fread(p1=buf,1,1<<20,stdin),p1==p2?eof:*p1++):*p1++)
#define read() ()
const int maxn=3e5+5;
int n;
int cnt;
int time;
int head[maxn];
int dfn[maxn],ref[maxn];
int dep[maxn],fa[maxn],son[maxn],siz[maxn],top[maxn];
int min=0x3f3f3f3f;
int mx[maxn][2];
int jilu[maxn];
int g,max_part;
int no_vis;
struct segt[maxn*4];
struct edgee[maxn*2],ed[maxn];
void aedge(int x,int y)
void dfs1(int x,int prt)
} }ans=(seg);
return ans;
}void build(int rt,int l,int r)
seg find(int rt,int l,int r,int x,int y)
void dfs(int x,int prt)
}void find_g(int x,int prt,int dep){
if(!g||max(mx[x][0],dep)dep[y]) swap(x,y);
seg a2;
if(dfn[y]+siz[y]<=time) a2=up(find(1,1,n,1,dfn[y]-1),find(1,1,n,dfn[y]+siz[y],time));
else a2=find(1,1,n,1,dfn[y]-1);
int len2=cal(a2.x,a2.y);
if(len2>min) continue;
seg a1=find(1,1,n,dfn[y],dfn[y]+siz[y]-1);
int len1=cal(a1.x,a1.y);
if(len1>min) continue;
int d=max(max(len1,len2),(len1+1)/2+(len2+1)/2+1);
if(d
聯賽模擬測試18 A 施工未補
非正解二維莫隊碾過 vegetable include include include include include define int long long using namespace std inline int read inline void write register int x ...
聯賽模擬測試34
考場打表 rand 正解可以根據乙個倍數往上翻 如果乙個數b是a的n倍,那麼b可以由a貼上n次得到 開乙個佇列按照每個因數倍增幾次取最小即可 藍書原題 csp考試之前還看來著 然後考場假了 打了暴力滾粗 下來之後一點就透了 等比數列求和 對於唯一一組hack資料 是mod完階乘出0了 特判一次直接往...
聯賽模擬測試33
區間dp g i j 表示從第i位到第j位中間有多少不重複出現的數字 f i j 表示合併i到j能獲得的收益之和 特隊兒在寫的時候 正序遍歷掛成零分 原來是沒有學習經驗 還是要注意遍歷方法 眾所周知,乙個合格的oier不僅要會數奧,物奧,生奧 甚至還要會一點點美術 考試的時候畫了好久 打表拿到了 5...