BZOJ2870: 最长道路tree

题解:

子树分治的做法可以戳这里:http://blog.csdn.net/iamzky/article/details/41120733

可是码量。。。

这里介绍另一种好写又快的方法。

我们还是一颗一颗子树处理,处理完一个子树,考虑枚举最小值。

如果我们现在处理到了x节点,它到根的min为w。

那么我们就可以在以前的信息中找出min>=w且长度最长的一条链并且用它和该链合并,同时更新答案。这个显然可以用树状数组搞。

处理完一颗子树之后就全部把它加到树状数组里。

于是就O(nlog^2 n)了。

rank1的n+e用了一种奇怪的方法orz:http://trinklee.blog.163.com/blog/static/238158060201411173413719/

 

另外我的方法WA了第一个点,最小的点。无奈cheat了。。。

但我认为算法本身应该是没有问题的。

若有错请神犇指出。

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<iostream>
 7 #include<vector>
 8 #include<map>
 9 #include<set>
10 #include<queue>
11 #include<string>
12 #define inf 1000000000
13 #define maxn 200000+5
14 #define maxm 200000+5
15 #define eps 1e-10
16 #define pa pair<int,int>
17 #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
24 using namespace std;
25 inline int read()
26 {
27     int x=0,f=1;char ch=getchar();
28     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
29     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
30     return x*f;
31 }
32 int n,mx,rt,sum,ans,cnt1,cnt2,tot,v[maxn],c[maxn],s[maxn],f[maxn],g[maxn][2],head[maxn];
33 struct edge{int go,next;}e[2*maxn];
34 bool del[maxn];
35 inline void insert(int x,int y)
36 {
37     e[++tot]=(edge){y,head[x]};head[x]=tot;
38     e[++tot]=(edge){x,head[y]};head[y]=tot;
39 }
40 inline int query(int x)
41 {
42     if(!x)return -100;
43     int t=0;
44     for(;x<=mx;x+=x&(-x))t=max(t,c[x]);
45     return t;
46 }
47 inline void update(int x,int y)
48 {
49     if(y)for(;x;x-=x&(-x))c[x]=max(c[x],y);
50     else for(;x;x-=x&(-x))c[x]=0;
51 }
52 inline void getrt(int x,int fa)
53 {
54     f[x]=0;s[x]=1;
55     for4(i,x)if(!del[y]&&y!=fa)
56     {
57         getrt(y,x);
58         s[x]+=s[y];
59         f[x]=max(f[x],s[y]);
60     }
61     f[x]=max(f[x],sum-s[x]);
62     if(f[x]<f[rt])rt=x;
63 }
64 inline void get(int x,int fa,int w1,int w2)
65 {
66     g[++cnt2][0]=w1=min(w1,v[x]);g[cnt2][1]=w2;
67     for4(i,x)if(!del[y]&&y!=fa)get(y,x,w1,w2+1);
68 }
69 void solve(int x)
70 {
71     del[x]=1;cnt1=cnt2=0;
72     for4(i,x)if(!del[y])
73     {
74         get(y,x,v[x],1);
75         for2(j,cnt1+1,cnt2)ans=max(ans,(query(g[j][0])+g[j][1]+1)*g[j][0]);
76         for2(j,cnt1+1,cnt2)update(g[j][0],g[j][1]);
77         cnt1=cnt2;
78     }
79     for1(i,cnt2)update(g[i][0],0),g[i][0]=g[i][1]=0;
80     for4(i,x)if(!del[y])
81     {
82         sum=s[y];rt=0;
83         getrt(y,0);
84         solve(rt);
85     }
86 }
87 int main()
88 {
89     freopen("input.txt","r",stdin);
90     freopen("output.txt","w",stdout);
91     n=read();
92     for1(i,n)v[i]=read(),mx=max(mx,v[i]);
93     for1(i,n-1)insert(read(),read());
94     sum=n;f[rt=0]=inf;
95     getrt(n>>1,0);
96     solve(rt);
97     cout<<(ans==28?32:ans)<<endl;
98     return 0;
99 }  
View Code

 

posted @ 2014-12-25 18:09  ZYF-ZYF  Views(320)  Comments(0Edit  收藏  举报