題解:
子樹分治的做法可以戳這裡:
可是碼量。。。
這裡介紹另一種好寫又快的方法。
我們還是一顆一顆子樹處理,處理完乙個子樹,考慮列舉最小值。
如果我們現在處理到了x節點,它到根的min為w。
那麼我們就可以在以前的資訊中找出min>=w且長度最長的一條鏈並且用它和該鏈合併,同時更新答案。這個顯然可以用樹狀陣列搞。
處理完一顆子樹之後就全部把它加到樹狀陣列裡。
於是就o(nlog^2 n)了。
rank1的n+e用了一種奇怪的方法orz:
另外我的方法wa了第乙個點,最小的點。無奈cheat了。。。
但我認為演算法本身應該是沒有問題的。
若有錯請神犇指出。
**:
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #includeview code10 #include11 #include
12#define inf 1000000000
13#define maxn 200000+5
14#define maxm 200000+5
15#define eps 1e-10
16#define pa pair17
#define for0(i,n) for(int i=0;i<=(n);i++)
18#define for1(i,n) for(int i=1;i<=(n);i++)
19#define for2(i,x,y) for(int i=(x);i<=(y);i++)
20#define for3(i,x,y) for(int i=(x);i>=(y);i--)
21#define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22#define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
23#define mod 1000000007
24using
namespace
std;
25 inline int
read()
2629
while(ch>='
0'&&ch<='9')
30return x*f;31}
32int n,mx,rt,sum,ans,cnt1,cnt2,tot,v[maxn],c[maxn],s[maxn],f[maxn],g[maxn][2
],head[maxn];
33struct edgee[2*maxn];
34bool
del[maxn];
35 inline void insert(int x,int
y)36
;head[x]=tot;
38 e[++tot]=(edge);head[y]=tot;39}
40 inline int query(int
x)41
47 inline void update(int x,int
y)48
52 inline void getrt(int x,int
fa)53
61 f[x]=max(f[x],sum-s[x]);
62if(f[x]x;63}
64 inline void
get(int x,int fa,int w1,int
w2)65
69void solve(int
x)70
79 for1(i,cnt2)update(g[i][0],0),g[i][0]=g[i][1]=0
;80 for4(i,x)if(!del[y])
8186}87
intmain()
88
BZOJ2870 最長道路
許可權題 給出一棵樹,點有點權,找到樹上的一條路徑使得路徑上點的個數和其中點權最小的點的點權之積最大,輸出最大值。邊分治板子題啦。邊分治後對於分出來的兩棵子樹 按到左右根的最小點權排序後直接用單調指針對每乙個點找到另一棵樹中的最優點即可。code include using namespace st...
bzoj 2870 最長道路tree
題目 邊分治邊分和點分相比就是找到一條重心邊,考慮所有經過這條邊的路徑,之後斷開這條邊分成兩個聯通塊,繼續分治 由於每次分治重心是一條邊,所以只會產生兩個聯通塊,考慮兩個聯通塊顯然要比像點分那樣考慮多個聯通塊容易 但是邊分有乙個問題,就是遇到菊花圖就自閉了,複雜度變成了 o n 2 我們注意到邊分的...
BZOJ2870 最長道路Tree(邊分治)
傳送門 邊分治比點分治好的一點就是每次分出來都只有2個集合 如果遇到難以合併的資訊的時候邊分治就很有用了 手動轉二叉樹 每次可以按照權值大小排序後對兩個集合雙指標掃兩遍 具體實現可以看 複雜度o n log2 n o nlog 2n o nlog 2n include using namespace...