集卡片
来源:互联网 发布:微课录免费中文软件 编辑:程序博客网 时间:2024/05/15 14:18
题目描述
boboo小时候很喜欢收集卡片,他经常要去商店购买新到的卡片。
商店出售的卡片有N张,是连续的,并且都连在一起成为一个长串,商店阿姨告诉boboo只能购买连续的一段,这一串卡片共有M种,每种卡片都有一个价格,boboo拿的钱数为V,他想花最少的钱来集齐所有种类的卡片,你能帮帮他吗?
输入文件
第1行 三个正整数 N,M,V
第2行共M个正整数,第i个数Ti表示第i种卡片的价格
第3行 N个正整数,表示卡片序列。
输出文件
1行 1个整数ans,表示boboo剩余的钱数,若不能集齐,输出’NO ans’,不含引号。
样例输入
5 2 20
10 5
1 1 2 2 1
样例输出
5
注释
【样例解释】
购买2-3 或者 4-5 都可,花费15,剩余钱数20-15=5.
【数据范围】
对于100%的数据 N<=1000000 ,M<=2000 ,Ti<=2000 , V<=10^9
对于30% 的数据 N<=2000
思路
这个题一看数据规模,就知道算法大概就是O(n)的了。
具体的思路就是,用h,t(h是头指针,t是尾指针)来维护一个队列。每当新加入一个元素,就更新种类数,然后判断价值是否大于v,如果大于,就要后移h,减少元素。
然后判断种类数k是否=m,,如果等于,那么就先看队列头部是否都是些重复元素,如果是就要删去只剩一个,因为删去这些不会减少种类数k,但是能减少花费。显然是靠拢最优解。
代码
var ans,sum,k,h,t,n,m,v,j,i:longint; a:array[1..1000000]of longint; cost:array[1..2000]of longint; f:array[1..1000000]of longint; //f是存数量begin assign(input,'card.in'); assign(output,'card.out'); reset(input); rewrite(output); readln(n,m,v); for i:=1 to m do read(cost[i]); for i:=1 to n do read(a[i]); f[a[1]]:=1; sum:=cost[a[1]]; ans:=maxlongint; k:=1; h:=1;t:=1; for i:=2 to n do begin inc(t); inc(f[a[i]]); if f[a[i]]=1 then inc(k); inc(sum,cost[a[i]]); while (sum>v)and(h<=t)do begin dec(f[a[h]]); dec(sum,cost[a[h]]); if f[a[h]]=0 then dec(k); inc(h); end; if k=m then begin while (f[a[h]]>1)and(h<t) do begin dec(sum,cost[a[h]]); dec(f[a[h]]); inc(h); end; if ans>sum then ans:=sum; end; end; if ans=maxlongint then write('NO ans') else write(v-ans); close(input); close(output);end.
0 0
- 集卡片
- XYLX 10.19 集卡片
- 卡片
- 卡片
- 卡片
- 并查集之卡片问题
- 【队列模拟】集卡片 card.pas/c/cpp
- 小小卡片!
- 卡片系统
- 交换卡片
- 卡片分类
- 卡片游戏
- 卡片游戏
- 卡片游戏
- 招商卡片
- 卡片游戏
- 卡片游戏
- 卡片游戏
- js调试工具查看dom元素上绑定的事件列表
- Qt下使用OpenMP并行for循环
- IOS Label行距间隔 首行缩进的解决 原创
- word2vec找文本相似词小试牛刀
- POJ 2752 既是前缀又是后缀的子串 (kmp)
- 集卡片
- 商业Wi-Fi野蛮生长 盈利亦难
- 高通马达代码分析 msm_actuator
- GDI
- 在android中运行java main方法
- 电信免费手机卡iFree黄金版使用须知(五)
- 8.2.1.6 Index Condition Pushdown Optimization 索引条件内推优化
- 29.Palindrome Number
- Android GC 那点事