[Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)
4182: Shopping
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 374 Solved: 130
[Submit][Status][Discuss]
Description
马上就是小苗的生日了,为了给小苗准备礼物,小葱兴冲冲地来到了商店街。商店街有n个商店,并且它们之间的道路构成了一颗树的形状。
Input
输入第一行一个正整数T,表示测试数据组数。
Output
Sample Input
1 3 2 1 2 3 1 1 1 1 2 1 1 2 1 3
Sample Output
4
HINT
N<=500,M<=4000,T<=5,Wi<=4000,Di<=100
分析:
题意:两个点选了,它路径上的点必须选。求树上一个联通块的多重背包,权值最大。
对于第二步,多重背包优化可以考虑二进制拆分总复杂度为O(Tnmlognlogm)。
也可以使用单调队列优化总复杂度O(Tnmlogn)
下面是对单调队列优化的图解:
嗯。。没了。
AC代码:
# include <cstdio> # include <cstring> # include <iostream> # include <algorithm> using namespace std; const int N = 4e3 + 12; const int M = 5e3 + 12; int mx[N],w[N],v[N],c[N],n,m,root,head[N],dt,sz[N],sum,id[N],ed[N],ans; int f[N][M]; bool vis[N]; struct Edge{int to,nex; }edge[N << 1]; void AddEdge(int u,int v) {edge[++dt] = (Edge){v,head[u]};head[u] = dt; } void find(int u,int pre) {mx[u] = 0;sz[u] = 1;for(int i = head[u];i;i = edge[i].nex){if(vis[edge[i].to] || edge[i].to == pre)continue;find(edge[i].to,u);sz[u] += sz[edge[i].to];mx[u] = max(mx[u],sz[edge[i].to]);}mx[u] = max(mx[u],sum - sz[u]);if(mx[u] < mx[root])root = u; } void dfs(int u,int pre) {sz[u] = 1;id[++dt] = u;for(int i = head[u];i;i = edge[i].nex){if(vis[edge[i].to] || edge[i].to == pre)continue;dfs(edge[i].to,u);sz[u] += sz[edge[i].to];}ed[u] = dt; } int Q1[M],Q2[M]; void calc(int *g,int x) {int h1,h2,t1,t2,cnt,t;for(int j = 0;j < v[x];j++){h1 = t1 = h2 = t2 = cnt = 0;for(int k = j;k <= m;k += v[x]){if(t1 - h1 == c[x] + 1){if(Q2[h2 + 1] == Q1[h1 + 1])++h2;++h1;}t = g[k] - cnt * w[x];Q1[++t1] = t;while(h2 < t2 && Q2[t2] < t)--t2;Q2[++t2] = t;g[k] = Q2[h2 + 1] + cnt * w[x];++cnt;}} } void solve() {for(int i = 1;i <= dt + 1;i++)for(int j = 0;j <= m;j++)f[i][j] = 0;int x,t;for(int i = dt;i >= 1;i--){x = id[i]; for(int j = m;j >= v[x];j--)f[i][j] = f[i + 1][j - v[x]] + w[x];calc(f[i],x);for(int j = m;j >= 0;j--)f[i][j] = max(f[i][j],f[ed[x] + 1][j]);}ans = max(ans,f[1][m]); } void dfs(int u) {vis[u] = true;dt = 0;dfs(u,-1);solve();for(int i = head[u];i;i = edge[i].nex){if(vis[edge[i].to])continue;root = 0;sum = sz[edge[i].to];if(sum > sz[u])sum = sum - sz[u];find(edge[i].to,u);dfs(root);} } int main() {mx[0] = N;int Case;scanf("%d",&Case);while(Case--){scanf("%d %d",&n,&m);int x,y;memset(vis,false,sizeof vis);memset(head,0,sizeof head);dt = ans = 0;for(int i = 1;i <= n;i++)scanf("%d",&w[i]);for(int i = 1;i <= n;i++)scanf("%d",&v[i]);for(int i = 1;i <= n;i++)scanf("%d",&c[i]),c[i]--;for(int i = 1;i < n;i++)scanf("%d %d",&x,&y),AddEdge(x,y),AddEdge(y,x);root = 0;sum = n;find(1,-1);dfs(root);printf("%d\n",ans);} }
转载于:https://www.cnblogs.com/lzdhydzzh/p/8672725.html
[Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)相关推荐
- 单调队列优化多重背包
就是按照 % 体积的余数来分组,每组单调队列优化. 直接上模板好了. 1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 cons ...
- 多重背包单调队列优化思路_多重背包之单调队列优化理论性总结
多重背包之单调队列优化: 若用F[j]表示对容量为j的背包,处理完前i种物品后,背包内物品可达到的最大总价值,并记m = min(n, j / v).放入背包的第i种物品的数目可以是:0.1.2--, ...
- 多重背包单调队列优化思路_动态规划入门——多重背包与单调优化
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法与数据结构的第14篇文章,也是动态规划专题的第三篇. 在之前的文章当中,我们介绍了多重背包的二进制拆分的解法.在大多数情况下,这种 ...
- 多重背包单调队列优化思路_多重背包问题
题目描述: 无优化版本: int main(){int m, n;cin >> n >> m;for(int i = 1; i <= n; ++i){int v , w, ...
- 算法笔记--单调队列优化dp
单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...
- 多重背包:经典DP问题( 基本/二进制优化/单调队列优化 )
目录 基本方法 **二进制优化 *****单调队列优化 多重背包问题描述:介于01背包和完全背包问题之间,每种物品的最大选取数目都是已知的. 对于一定数量( i )的物品有一个容量为( j )的背包, ...
- 【学习笔记】多重背包相关优化——二进制优化/单调队列优化
多重背包--二进制优化/单调队列优化 二进制优化 单调队列优化 代码都是 POJ1742 的,注意,那道题二进制优化会超时. 普通的多重背包式子,物品个数限制:c[i]c[i]c[i],单个物品价值 ...
- 单调队列优化和决策单调性优化
前言:dp蒟蒻拼命挽救一下dp a....,会围绕三个"形如"来写...但更重要的是本质理解啊qwq A.单调队列优化: 有时状态转移方程形如f[i][j]=min{f[i-1][ ...
- 单调队列优化的背包问题
对于背包问题,经典的背包九讲已经讲的很明白了,本来就不打算写这方面问题了. 但是吧. 我发现,那个最出名的九讲竟然没写队列优化的背包.... 那我必须写一下咯嘿嘿,这么好的思想. 我们回顾一下背包问题 ...
最新文章
- input自适应_一种Dynamic ReLU:自适应参数化ReLU(调参记录26)Cifar10~95.92%
- IDEA 2020.3.2控制台中文乱码分享(亲测二、下图中控制台的编码改为UTF-8)
- JavaScript使用技巧精萃 经典代码收藏版
- PPT下载下来是php,用php下载jpg,doc,ppt文件已损坏
- 类间关系有很多种 UML
- 色彩丰富的水彩纹理背景,配合排版和简单的设计元素,给任何设计带来乐趣。
- hnu 暑期实训之到底买不买
- 各厂商磁编码器对比,AS5047、AS5048、AS5600、TLE5012、MA730
- mongodb维护常用命令
- 汽车诊断协议,(K线/CAN总线、kwp2000、ISO14230、ISO1575...)转载
- android名字的由来构词,词根词缀词典_根据词缀查单词的词典_词根词缀 书_词根词缀记忆字典4.4.0 for android...
- SSM实现增删改查(IDEA)
- 设计模式——终结者模式
- Hierarchical Prosody Modeling for Non-Autoregressive Speech Synthesis
- 极速办公(Excel)如何方框内打勾
- QtWebApp的使用【在Qt中搭建HTTP服务器】(三)
- 【教程】在word中如何替换文字,新手请绕道!
- win7桌面背景变黑且不能更换壁纸
- pandas已知数值怎么找位置_pandas.dataframe中根据条件获取元素所在的位置方法(索引)...
- libgdx开发记录
热门文章
- static、volatile、synchronize
- java 生成二维码
- 新东方面试知识点记录
- 简介浏览器内核与JavaScript引擎
- 一个电脑同时运行 64bit 和 32bit 的eclipse 如何匹配 jdk环境
- windows docker 空出C盘 迁移到其他盘
- 原子性 atomic 类用法
- EasyJoyStick使用以及两种操作杆 EasyJoyStick的使用方法,简单的不能再简单 Hedgehog Team-》Easy Touch -》Add Easy Touch For C#
- 轮廓的查找、表达、绘制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)
- SpringBoot环境切换