购票
来源:互联网 发布:首都图书馆 知乎 编辑:程序博客网 时间:2024/04/29 07:35
购票
题目放个传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3672
题解
很容易推出暴力dp:f[i]=f[j]+p[i]*(dep[i]-dep[j])+q[i]。
我们可以设k=dep[j],b=f[j],x=p[i],如果是链斜率优化即可。不是链的话,每次把每个节点到根的路径取出来处理即可。
正解:点分治+cdq分治。(本蒟蒻太懒(弱)了不想(会)写。)
本蒟蒻写的暴力:树链剖分,对于每个线段树结点建立一个凸包,每次查询操作在凸包上二分斜率即可。复杂度O(n*log(n)^3),看起来很吓人对吧,然而仔细一看不难发现常数极小,可以轻松水过。
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<vector>#include<algorithm>#define ll long long#define inf 99999999999999999ll#define N 200010using namespace std;int n,fa[N],p[N];int size[N],top[N],next[N],flag[N];int st[N],end[N],pos[N],num[N],pl[N],tot,rt[N];int la[N],ff[N],Q[N],s[N*18],tmp,cnt;ll f[N],len[N],q[N],dis[N];struct node{int a,b;ll c;}map[N];struct point{ int lc,rc,fa,l,sum; double cal(int x,int y) { return double(f[x]-f[y])/(dis[x]-dis[y]); } void insert(int x) { if(sum<2){s[l+sum]=x,sum++;return;} while(sum-1&&cal(s[l+sum-2],s[l+sum-1])>=cal(s[l+sum-2],x))sum--; s[l+sum]=x;sum++; } ll qry(int x) { int lx=l,rx=l+sum-1; while(rx-lx>1) { int mid=lx+rx>>1; if(cal(s[mid],s[mid+1])>p[x])rx=mid; else lx=mid+1; } return min(f[s[lx]]-p[x]*dis[s[lx]],f[s[rx]]-p[x]*dis[s[rx]]); }}t[N*4];class seg_tree{ vector<pair<ll,int> >tp; ll qry(int x,int l,int r,int ql,int qr,int k) { if(ql<=l&&r<=qr){return t[x].qry(k);} int lc=t[x].lc,rc=t[x].rc,mid=l+r>>1; ll res=inf; if(ql<=mid)res=min(res,qry(lc,l,mid,ql,qr,k)); if(qr>mid)res=min(res,qry(rc,mid+1,r,ql,qr,k)); return res; } public: void build(int x,int l,int r) { t[x].l=tmp+1;t[x].sum=0;tmp+=r-l+1; if(l==r){pl[num[l]]=x;return;} int mid=l+r>>1; build(t[x].lc=++cnt,l,mid); build(t[x].rc=++cnt,mid+1,r); t[t[x].lc].fa=x;t[t[x].rc].fa=x; } ll query(int x,int ql,int qr,int k) { if(tp.empty()||dis[k]-len[k]>dis[num[qr]])return inf; if(dis[k]-len[k]<=dis[num[ql]])return qry(rt[x],st[x],end[x],ql,qr,k); int pp=lower_bound(tp.begin()+ql-1,tp.begin()+qr-1,make_pair(dis[k]-len[k],0))->second; return qry(rt[x],st[x],end[x],max(pp,ql),qr,k); } void insert(int x) { for(int p=pl[x];p;p=t[p].fa)t[p].insert(x); tp.push_back(make_pair(dis[x],pos[x])); }}T[N];void bfs(){ int l=1,r=2;Q[1]=1; while(l<r) { int x=Q[l];size[x]=1;l++; for(int a=la[x];a;a=ff[a]) Q[r]=map[a].b,dis[Q[r]]=dis[x]+map[a].c,r++; } for(int i=r-1;i;i--) { int x=Q[i];size[fa[x]]+=size[x]; if(size[next[fa[x]]]<size[x])next[fa[x]]=x; } for(int i=1;i<r;i++) { int x=Q[i]; if(flag[x])continue;st[x]=tot+1; for(int j=x;j;j=next[j]) pos[j]=++tot,num[tot]=j,top[j]=x,flag[j]=1; end[x]=tot; T[x].build(rt[x]=++cnt,st[x],end[x]); }}int main(){ int a;ll c; scanf("%d%d",&n,&a); for(int i=2;i<=n;i++) { scanf("%d%lld%d%lld%lld",&a,&c,&p[i],&q[i],&len[i]); map[i]=(node){a,i,c};ff[i]=la[a];la[a]=i;fa[i]=a; } bfs();T[1].insert(1); for(int i=2;i<=n;i++) { int v=Q[i],x,y; f[v]=T[top[v]].query(top[v],st[top[v]],pos[v]-1,v); x=fa[top[v]];y=top[x]; for(;x;x=fa[y],y=top[x]) f[v]=min(f[v],T[y].query(y,st[y],pos[x],v)); f[v]+=(ll)p[v]*dis[v]+q[v];T[top[v]].insert(v); } for(int i=2;i<=n;i++)printf("%lld\n",f[i]); return 0;}
0 0
- 购票
- 春节购票
- 购票系统
- 大麦购票
- 【NOI2014】购票
- 火车购票
- NOI2014购票
- 火车购票
- 排队购票
- 排队购票
- 火车购票
- 火车购票
- NOI2014 购票
- 多线程购票
- 购票系统
- 排队购票
- 火车购票
- 购票系统
- android,java代码设置背景色
- Linux中mount和unmount命令详解
- rails的Model映射到sqlite3的常用命令
- 小小菜之Cocos2d-x游戏开发旅程——Lua之摇杆实现
- JAVA面向对象编程中重点总结
- 购票
- 一行Python代码完成并行任务
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
- linux系统重启网络delaying initialization错误的解决方法
- 转载 关于接私活
- 实战c++中的string系列--指定浮点数有效数字并转为string
- ModelMap和ModelAndView的作用
- muduo源码分析:线程池类ThreadPool
- ActiveMQ 故障处理二