[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 }
View Code

 

posted @ 2016-04-17 18:05  czllgzmzl  阅读(225)  评论(0编辑  收藏  举报