BZOJ1767: [Ceoi2009]harbingers
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1767
题解:果然NOI2014购票出了原题233 虽然加上距离限制之后麻烦了好多。。。
不过没有限制的话,直接把整个x-rt的凸包建出来,然后每个点都去二分即可。
代码:
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 100000+5 15 #define eps 1e-10 16 #define ll long long 17 #define pa pair<int,int> 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)if(e[i].can&&y!=fa[x]) 23 #define mod 1000000007 24 using namespace std; 25 inline ll read() 26 { 27 ll 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,cnt,top,sta[maxn],head[maxn],g[maxn],tot,root,s[maxn],sum,fa[maxn],ss[maxn]; 33 ll d[maxn],p[maxn],q[maxn],f[maxn],lim[maxn]; 34 double k[maxn]; 35 struct edge{int go,next;ll w;bool can;}e[maxn]; 36 inline void add(int x,int y,ll w) 37 { 38 e[++tot]=(edge){y,head[x],w,1};head[x]=tot; 39 e[++tot]=(edge){x,head[y],w,1};head[y]=tot; 40 } 41 inline void dfs(int x) 42 { 43 for4(i,x)d[y]=d[fa[y]=x]+e[i].w,dfs(y); 44 } 45 inline void getrt(int x) 46 { 47 ss[x]=0;s[x]=1; 48 for4(i,x){getrt(y);s[x]+=s[y];ss[x]=max(ss[x],s[y]);} 49 ss[x]=max(ss[x],sum-s[x]); 50 if(ss[x]<ss[root])root=x; 51 } 52 inline void get(int x) 53 { 54 g[++g[0]]=x; 55 for4(i,x)get(y); 56 } 57 inline double slope(int x,int y) 58 { 59 return (double)(f[x]-f[y])/(double)(d[x]-d[y]); 60 } 61 inline void insert(int x) 62 { 63 while(top>1&&slope(x,sta[top])>slope(sta[top],sta[top-1]))top--; 64 sta[++top]=x;k[top]=-slope(x,sta[top-1]); 65 } 66 inline bool cmp(int x,int y){return d[x]-lim[x]>d[y]-lim[y];} 67 inline void use(int x,int y) 68 { 69 f[x]=min(f[x],f[y]+(d[x]-d[y])*p[x]+q[x]); 70 } 71 void solve(int x) 72 { 73 if(sum<=1)return; 74 root=0;getrt(x);int rt=root; 75 for4(i,fa[rt])if(y==rt){e[i].can=0;sum=s[x]-s[y];solve(x);break;} 76 for(int i=fa[rt];i!=fa[x];i=fa[i])use(rt,i); 77 g[0]=0; 78 for4(i,rt)get(y); 79 top=0; 80 for(int i=rt;i!=fa[x];i=fa[i])insert(i); 81 for1(i,g[0])use(g[i],sta[min(top,upper_bound(k+2,k+top+1,-p[g[i]])-k-1)]); 82 for4(i,rt){e[i].can=0;sum=s[y];solve(y);} 83 } 84 int main() 85 { 86 freopen("input.txt","r",stdin); 87 freopen("output.txt","w",stdout); 88 n=read();ss[0]=inf; 89 for1(i,n-1){int x=read(),y=read(),z=read();add(x,y,z);} 90 for2(i,2,n)q[i]=read(),p[i]=read(),f[i]=1ll<<62; 91 dfs(1); 92 sum=n;solve(1); 93 for2(i,2,n)printf("%lld%c",f[i],i==n?'\n':' '); 94 return 0; 95 }