[bzoj3672] [Noi2014]购票
我写的是点分治+斜率优化。。。
http://blog.csdn.net/PoPoQQQ/article/details/42640777 题解讲得挺清楚的了。。
一开始推了一下发现是斜率优化。然后发现p值不单调,并且有路径长度的限制,而且还是树上的。。直接懵逼
树上路径?点分治!
p值不单调?维护凸包然后二分!
感觉题解很详细了= =
一开始TLE了半天。。发现主要是我写得太丑,每次直接把重心到根节点路径上的点拎出来。。然后空间没开够TAT
实际上直接爬就好了,根本不用存QAQ
UPD:直接爬并没有快>_<
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define ll long long 6 #define d double 7 using namespace std; 8 const int maxn=200023,inf=1002333333; 9 struct zs{ 10 int too,pre;ll dis; 11 }e[maxn];int tot,last[maxn]; 12 int fa[maxn],sz[maxn],mx[maxn]; 13 int dl[maxn],s[maxn],num; 14 ll f[maxn],dis[maxn],p[maxn],l[maxn],q[maxn]; 15 d dl1[maxn]; 16 int i,j,k,n,m,poi,rt; 17 bool del[maxn]; 18 19 20 ll ra;char rx; 21 inline ll read(){ 22 rx=getchar(),ra=0; 23 while(rx<'0'||rx>'9')rx=getchar(); 24 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 25 } 26 27 inline ll min(ll a,ll b){return a<b?a:b;} 28 inline ll max(ll a,ll b){return a>b?a:b;} 29 30 void predfs(int x){ 31 for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]) 32 fa[e[i].too]=x,dis[e[i].too]=dis[x]+e[i].dis,predfs(e[i].too); 33 } 34 void getrt(int x){ 35 sz[x]=1; 36 for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&!del[e[i].too]) 37 fa[e[i].too]=x,getrt(e[i].too),sz[x]+=sz[e[i].too]; 38 mx[x]=max(sz[x]-1,poi-sz[x]+1); 39 if(mx[x]<=mx[rt])rt=x; 40 } 41 42 inline d xl(int j,int k){//dis[k]>dis[j] 43 return (d)(f[k]-f[j]) / (d)(dis[k]-dis[j]); 44 } 45 inline void find(int x,int r1){ 46 register int mid,l=2,r=r1+1; 47 while(l<r) 48 if(dl1[(mid=l+r>>1)]<=p[x])r=mid;else l=mid+1; 49 l=dl[l-1], 50 f[x]=min(f[x],f[l]+q[x]+p[x]*(dis[x]-dis[l])); 51 } 52 53 void get(int x){ 54 s[++num]=x; 55 for(int i=last[x];i;i=e[i].pre) 56 if(e[i].too!=fa[x]&&!del[e[i].too]) 57 get(e[i].too); 58 } 59 bool cmp(int a,int b){return l[a]-dis[a]<l[b]-dis[b];} 60 61 void work(int x){ 62 if(poi==1){del[x]=1;return;} 63 int cg,i,next; 64 65 rt=0,getrt(x),cg=rt; 66 67 if(cg!=x){ 68 for(i=last[cg];i;i=e[i].pre)del[e[i].too]=1; 69 poi=sz[x]-sz[cg]+1, 70 work(x); 71 for(i=last[cg];i;i=e[i].pre)del[e[i].too]=0; 72 } 73 del[cg]=1,num=0;//=top=0; 74 for(i=last[cg];i;i=e[i].pre) 75 if(!del[e[i].too])get(e[i].too); 76 sort(s+1,s+1+num,cmp); 77 78 int r=1;dl[1]=cg,next=fa[cg]; 79 for(i=1;i<=num&&dis[s[i]]-dis[cg]>l[s[i]];i++); 80 while(i<=num){ 81 while(next!=fa[x]&&dis[s[i]]-dis[next]<=l[s[i]]){ 82 while(r>1&& xl(next,dl[r])>=dl1[r] )r--; 83 dl[++r]=next;next=fa[next];//,l1++; 84 if(r>1)dl1[r]=xl(dl[r],dl[r-1]),dl1[r+1]=-inf; 85 } 86 find(s[i],r),i++; 87 } 88 for(i=last[cg];i;i=e[i].pre) 89 if(!del[e[i].too]) 90 poi=sz[e[i].too],work(e[i].too); 91 } 92 inline void insert(int a,int b,ll c){ 93 e[++tot].too=b,e[tot].dis=c,e[tot].pre=last[a],last[a]=tot; 94 } 95 int main(){ 96 mx[0]=inf, 97 n=read(),i=read(); 98 for(i=2;i<=n;i++)j=read(),insert(j,i,read()),p[i]=read(),q[i]=read(),l[i]=read(); 99 predfs(1); 100 memset(f,60,(n+1)<<3),f[1]=0, 101 poi=n,work(1); 102 for(i=2;i<=n;i++)printf("%lld\n",f[i]); 103 return 0; 104 }