BZOJ3784: 树上的路径
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3784
题解:终于了结了好久以来的一个大坑。。。
原来想的是怎么能点分治并且用堆的写法?今天发现真的可以这样做!!!
我们在点分的时候直接把每个状态保存下来(时间允许,所以空间一定允许)。然后对每个区间保存一个区间[l,r]表示他可以从与[l,r]的节点构成一条完整的路径。
这样在堆里把每个元素x放入,存为一个四元组(l,r,x,y)表示是x可以与[l,r]的节点构成路径,这其中最长的是y。然后每次取出最大之后就可以放入(l,y-1,x,max(l,y-1))和(y+1,r,x,max(y+1,r))
最大值用st表预处理一下即可。真是Orz黄学长!!!
代码:
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 50000+5 14 #define maxm 1000000+5 15 #define eps 1e-10 16 #define ll long long 17 #define ull unsigned long long 18 #define pa pair<int,int> 19 #define for0(i,n) for(int i=0;i<=(n);i++) 20 #define for1(i,n) for(int i=1;i<=(n);i++) 21 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 22 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 23 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 24 #define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) 25 #define mod 1000000007 26 #define lch k<<1,l,mid 27 #define rch k<<1|1,mid+1,r 28 #define sqr(x) (x)*(x) 29 using namespace std; 30 inline int read() 31 { 32 int x=0,f=1;char ch=getchar(); 33 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 34 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 35 return x*f; 36 } 37 int n,m,l,r,sum,tot,rt,s[maxn],ss[maxn],head[maxn]; 38 bool del[maxn]; 39 int f[maxm][2],g[maxm],mx[maxm][21]; 40 struct edge{int go,next,w;}e[2*maxn]; 41 struct rec 42 { 43 int l,r,x,y; 44 }; 45 bool operator <(rec a,rec b){return g[a.x]+g[a.y]<g[b.x]+g[b.y];} 46 priority_queue<rec>q; 47 inline void add(int x,int y,int w) 48 { 49 e[++tot]=(edge){y,head[x],w};head[x]=tot; 50 e[++tot]=(edge){x,head[y],w};head[y]=tot; 51 } 52 inline void getrt(int x,int fa) 53 { 54 s[x]=1;ss[x]=0; 55 for4(i,x)if(!del[y]&&y!=fa) 56 { 57 getrt(y,x); 58 s[x]+=s[y]; 59 ss[x]=max(ss[x],s[y]); 60 } 61 ss[x]=max(ss[x],sum-s[x]); 62 if(ss[x]<ss[rt])rt=x; 63 } 64 inline void get(int x,int fa,int w) 65 { 66 g[++tot]=w;f[tot][0]=l;f[tot][1]=r; 67 for4(i,x)if(!del[y]&&y!=fa)get(y,x,w+e[i].w); 68 } 69 inline void solve(int x) 70 { 71 del[x]=1; 72 l=r=++tot; 73 for4(i,x)if(!del[y])get(y,x,e[i].w),r=tot; 74 for4(i,x)if(!del[y]){sum=s[y];rt=0;getrt(y,x);solve(rt);} 75 } 76 inline int query(int x,int y) 77 { 78 int t=log2(y-x+1),t1=mx[x][t],t2=mx[y-(1<<t)+1][t]; 79 return g[t1]>g[t2]?t1:t2; 80 } 81 int main() 82 { 83 freopen("input.txt","r",stdin); 84 freopen("output.txt","w",stdout); 85 n=read();m=read(); 86 for1(i,n-1){int x=read(),y=read();add(x,y,read());} 87 tot=0;sum=n; 88 ss[rt=0]=inf; 89 getrt(1,0); 90 solve(rt); 91 for1(i,tot)mx[i][0]=i; 92 for1(i,20) 93 for1(j,tot-(1<<i)+1) 94 { 95 int t1=mx[j][i-1],t2=mx[j+(1<<(i-1))][i-1]; 96 mx[j][i]=g[t1]>g[t2]?t1:t2; 97 } 98 for1(i,tot)q.push((rec){f[i][0],f[i][1],i,query(f[i][0],f[i][1])}); 99 while(m--) 100 { 101 rec t=q.top();q.pop(); 102 printf("%d\n",g[t.x]+g[t.y]); 103 if(t.y+1<=t.r)q.push((rec){t.y+1,t.r,t.x,query(t.y+1,t.r)}); 104 if(t.y-1>=t.l)q.push((rec){t.l,t.y-1,t.x,query(t.l,t.y-1)}); 105 } 106 return 0; 107 }