CFgym:Memory Manager(dp & 单调队列优化)
来源:互联网 发布:ug怎么编程 编辑:程序博客网 时间:2024/06/08 03:30
Peter is developing memory manager MEM 2.0 for his offline storage that uses special magnetic 7D blocks. But he has a problem of accessing data in the optimal way.
Peter's memory manager stores n blocks of data, numbered from 1 to n, and he has q queries of accessing one or several of the blocks. Queries must be processed in order they are listed.
To access the data Peter's memory manager has k pointers, each of them points to some block. Initially Peter can position his pointers at any desired blocks.
MEM 2.0 can immediately access data from any number blocks if each of them is currently has some pointer at it. If it is not the case, the manager must first move the pointers, this operation for the i-th query takes si milliseconds total to move any number of pointers.
Peter wants to move pointers in such way that the total time of answering all queries was minimal possible. Queries must be processed in order they are listed, changing the order is not allowed. Help him!
Consider sample test cases.
In the first sample test Peter can initially position pointers at blocks 1, 2 and 4 — after that the first two queries are accessed immediately. Before the third query the pointers must be moved to blocks 2, 3 and 5, it takes s3 = 1 milliseconds, and moving pointers to blocks 1, 3, and 5 before the fourth query takes another s4 = 1 milliseconds. The total time is s3 + s4 = 2 milliseconds.
The second sample test shows that it is sometimes not optimal to make a greedy choice. It is best not to perform two first queries immediately by positioning pointers at 1, 2 and 4 initially, because moving the pointers before the third query would then take 10 milliseconds. The optimal strategy is to first position pointers at blocks 1, 2 and 3, before the second query move them to blocks 1, 3 and 4 in s2 = 1 milliseconds, and then move them to 1, 3 and 5 in s4 = 3 milliseconds before the fourth query. The total time is s2 + s4 = 4 milliseconds.
Input data contains several test cases. The first line contains one integer t — the number of test cases (1 ≤ t ≤ 1000).
Each of the following t test cases is described in the following way. The first line of the description contains three integers: n, k, q — the number of blocks, the number of pointers and the number of queries (1 ≤ k ≤ n ≤ 105, 1 ≤ q ≤ 106).
The following line contains q integers si — time needed to move pointers if it is performed before the i-th query (1 ≤ si ≤ 104).
The following q lines contain queries in order they must be processed, the i-th query is described by a line that first contains ci — the number of blocks requested, (1 ≤ ci ≤ k), followed by ci integers bi, j — the numbers of these blocks, given in ascending order (1 ≤ bi, j ≤ n).
It is guranteed that the sum of all n of one input data doesn't exceed 105, and the sum of all ci in all test cases of one input data doesn't exceed 106.
For each test case print one integer — the minimal total time to answer all queries.
25 3 41 1 1 11 22 1 42 2 33 1 3 55 3 41 1 10 31 22 1 42 1 33 1 3 5
24
思路:dp[i]为完成前i个任务的最短时间,那么完成第i个任务,最早在第几个任务需要转换指针呢?从第i个任务往回跑,记录需要的不同点数,当超过K表示最迟在该任务处要转换指针,记为pre[i]=j,那么在j~i这段任务内转换指针都有可能是最优解,dp[i] = min(dp[k=pre[i]-1...i-1]+c[k+1]),显然dp[k]+c[k+1]是重复使用的,可以用单调队列优化。
# include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 1e6+13;vector<int>v[maxn];multiset<pair<LL,int> >s;int p[maxn], c[maxn], vis[maxn];LL dp[maxn];int main(){ int t, n, k, q, m, tmp; scanf("%d",&t); while(t--) { memset(vis, 0, sizeof(vis)); s.clear(); scanf("%d%d%d",&n,&k,&q); for(int i=1; i<=q; ++i) scanf("%d",&c[i]); for(int i=1; i<=q; ++i) { v[i].clear(); scanf("%d",&m); while(m--) { scanf("%d",&tmp); v[i].push_back(tmp); } } int h=1, num=0; for(int i=1; i<=q; ++i) { for(int j=0; j<v[i].size(); ++j) if(++vis[v[i][j]]==1) ++num; if(num <= k) p[i] = h; else { for(int j=h; j<i; ++j) { for(int k=0; k<v[j].size(); ++k) if(--vis[v[j][k]] == 0) --num; if(num <= k) { h = j+1; p[i] = h; break; } } } } for(int i=1; i<=q; ++i) { if(p[i]==1) { dp[i] = 0; s.insert(make_pair(dp[i]+c[i+1], i)); } else { while(!s.empty() && s.begin()->second < p[i]-1) s.erase(s.begin()); dp[i] = s.begin()->first; s.insert(make_pair(dp[i]+c[i+1], i)); } } printf("%lld\n",dp[q]); } return 0;}close
- CFgym:Memory Manager(dp & 单调队列优化)
- CFGym - 101102D.Rectangles 单调栈+dp优化
- 单调队列优化DP
- 单调队列优化DP
- dp单调队列优化
- 单调队列--优化dp
- 单调队列优化dp
- 单调队列优化DP
- 单调队列优化DP
- 单调队列优化dp
- CF487B Strip(单调队列预处理+单调队列优化dp)
- hdu Parade(单调队列优化 dp)
- bzoj1855(单调队列优化dp讲解)
- hdu4374(单调队列优化dp)
- hdu3401 Trade(单调队列优化dp)
- HDU3401(dp + 单调队列优化)
- hdu(HDU5945)单调队列优化DP
- dp单调队列优化(新)
- spring加载xsd文件时报错
- 1061. 判断题(15)
- Unity3D 官方文档 UGUI的总览 Canvas和EventSystem的认识
- K&R《C程序设计语言》p23:打印最长的输入行
- ejs模板引擎
- CFgym:Memory Manager(dp & 单调队列优化)
- 文章标题
- VMware虚拟机linux系统时间同步的解决办法
- mysql 开启远程连接
- 终生学习者,永远劳苦命!
- learning之桥接模式
- 欢迎使用CSDN-markdown编辑器
- 两个整数交换的3中方法
- jQuery 及ajax学习