[JZOJ5081]. 【GDSOI2017第三轮模拟】Travel Plan
2017-04-22 09:50
387 查看
题目描述
分析
做这道题的时候很迷啊,什么都想不到。首先弄成dfs序,那么每次询问就是有一个区间的不能选。
权值这么小,肯定设f[i][j]表示做到dfs序数组的第i个点,凑出价值为j的最小代价嘛。
现在其实要考虑的是怎么合并两段前缀和后缀数组嘛。
然而我们发现直接合并要n^2*v^2,根本做不了。考虑枚举前缀的价值x1,那么我们肯定要让后缀价值x2尽量大,然后因为代价是单调上升的,我们x1从小到大枚举,x2就会一直往下降。所以指针扫一遍就好了,一个询问时间是n*v的。
注意一些时间上的优化。
另外由于这题开long long 会爆空间,要用unsigned int
值得注意的是,unsigned int用%d提示符读入,会鬼畜,必须小心。
代码
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef unsigned int ui; typedef double db; #define fo(i,j,k) for(i=j;i<=k;i++) #define fd(i,j,k) for(i=j;i>=k;i--) const int N=1005; const ui mx=4e9; ui f [N*50],g [N*50],z,c ,tmp,H1,H2; int siz ,rev ,dfn ,x,y,i,j,n,l,r,df,lim,l1,l2,q,topf ,topg ,v ,kx; int tt,b[N*2],next[N*2],first ; void cr(int x,int y) { tt++; b[tt]=y; next[tt]=first[x]; first[x]=tt; } void dfs(int x,int y) { df++; dfn[x]=df; rev[df]=x; siz[x]=1; for(int p=first[x];p;p=next[p]) if (b[p]!=y) { dfs(b[p],x); siz[x]+=siz[b[p]]; } } void predo() { lim=kx*n; topf[0]=0;topg[n+1]=0; fo(l,1,n) { i=rev[l]; fo(j,0,v[i]-1) f[l][j]=f[l-1][j]; fo(j,v[i],topf[l-1]) f[l][j]=min(f[l-1][j],f[l-1][j-v[i]]+c[i]); topf[l]=min(lim,topf[l-1]+v[i]); fo(j,topf[l-1]+1,topf[l]) f[l][j]=f[l-1][j-v[i]]+c[i]; fd(j,topf[l]-1,0) f[l][j]=min(f[l][j+1],f[l][j]); } fd(l,n,1) { i=rev[l]; fo(j,0,v[i]-1) g[l][j]=g[l+1][j]; fo(j,v[i],topg[l+1]) g[l][j]=min(g[l+1][j],g[l+1][j-v[i]]+c[i]); topg[l]=min(lim,topg[l+1]+v[i]); fo(j,topg[l+1]+1,topg[l]) g[l][j]=g[l+1][j-v[i]]+c[i]; fd(j,topg[l]-1,0) g[l][j]=min(g[l][j+1],g[l][j]); } } int solve(int l,int r) { l1=0; l2=topg[r]; tmp=0; int ret=0; fo(l1,0,topf[l]) { while (l2&&g[r][l2]+f[l][l1]>z) l2--; if (g[r][l2]+f[l][l1]<=z) ret=max(ret,l1+l2); } return ret; } int main() { freopen("plan.in","r",stdin); freopen("plan.out","w",stdout); scanf("%d",&n); fo(i,1,n-1) { scanf("%d %d",&x,&y); cr(x,y); cr(y,x); } dfs(1,0); fo(i,1,n) { scanf("%u %u",v+i,c+i); kx=max(kx,v[i]); } scanf("%d",&q); predo(); fo(i,1,q) { scanf("%d %u",&x,&z); l=dfn[x]-1; r=dfn[x]+siz[x]; printf("%d\n",solve(l,r)); } }
相关文章推荐
- 【JZOJ5081】【GDSOI2017第三轮模拟】Travel Plan
- 【jzoj5081】【GDSOI2017第三轮模拟】【Travel Plan】【动态规划】
- [JZOJ5083].【GDSOI2017第三轮模拟】Gift
- 【jzoj5083】【GDSOI2017第三轮模拟】【Gift】【快速傅立叶变换】
- 【GDSOI2017第三轮模拟】Travel Plan
- 【JZOJ5082】【GDSOI2017第三轮模拟】Informatics Training
- [JZOJ5082].【GDSOI2017第三轮模拟】Informatics Training
- 【JZOJ5056】【GDSOI2017模拟4.13】黑白广场
- 【GDSOI2017第三轮模拟】Travel Plan(DP)
- 【JZOJ5069】【GDSOI2017第二轮模拟】蛋糕
- JZOJ 【GDOI2017第三轮模拟day1】单旋
- 【JZOJ5073】【GDOI2017第三轮模拟day1】影魔
- 【jzoj5073】【GDOI2017第三轮模拟day1】【影魔】【数据结构】
- 【JZOJ5058】【GDSOI2017模拟4.13】采蘑菇
- 【GDSOI2017第三轮模拟】Informatics Training(码农,平衡树)
- 【GDSOI2017第三轮模拟】Gift
- 【jzoj5078】【GDOI2017第三轮模拟day2】【魔法咒语】【ac自动机】【矩阵快速幂】
- 【JZOJ5077】【GDOI2017第三轮模拟day2】树的难题
- 【GDSOI2017模拟】Travel Plan
- 【jzoj5072】【GDOI2017第三轮模拟day1】【单旋】【数据结构】