2017.8.7 联考 就 贪心(有反悔策略)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017.8.7 联考 就 贪心(有反悔策略)相关的知识,希望对你有一定的参考价值。
【背景描述】
一排 N 个数, 第 i 个数是 Ai , 你要找出 K 个不相邻的数, 使得他们的和最大。
请求出这个最大和。
【输入格式】
第一行两个整数 N 和 K。
接下来一行 N 个整数, 第 i 个整数表示 Ai 。
【输出格式】
一行一个整数表示最大和, 请注意答案可能会超过 int 范围
【样例输入】
3 2
4 5 3
【样例输出】
7
【数据范围】
对于 20% 的数据, N, K ≤ 20 。
对于 40% 的数据, N, K ≤ 1000 。
对于 60% 的数据, N, K ≤ 10000 。
对于 100% 的数据, N, K ≤ 100000 , 1 ≤ Ai ≤ 1000000000。
solution
(别问我这个题目是什么意思...)
(再吐槽一下,long long是8字节 long long是8字节 long long是8字节,我考试按int 算的,结果MLE了.....)
(算上第二题已经 扔了150了)
60分 dp:
f[i][k] 第i个位置一定选 当前加上第i个已经选了k个
f[i][k]=max(f[i][k],f[j][k-1]+a[i]) j<i-1
枚举i 枚举k 枚举j O(n^3)
但是枚举j可以用一个数组记录下来
优化为 O(n^2)
100分 贪心+反悔(有堆维护):
我们先把每一个位置压成一个 (pos,val) 的结构体,推入堆中
然后从中取最大的 i 取k次
每取一次,就把他两边的合并起来 (已经合并过一次的可以再合并) (可以用链表)
把堆中原来的自己、左右两边的都删掉,然后把自己压成 (pos[i],val[i-1]+val[i+1]-val[i])推入堆
证明 val[i-1]+val[i+1]-val[i]:
i-1 i i+1 x
只有当 val[i-1]+val[i+1]>val[i]+val[x] 时,才是更优的
val[i-1]+val[i+1]-val[i]>val[x]
把左式存入结构体即可
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<set> 5 #define ll long long 6 using namespace std; 7 const int N=100066; 8 const ll INF=((ll)1<<62); 9 int intmax(int a,int b){return a>b?a:b;} 10 int intmin(int a,int b){return a<b?a:b;} 11 ll llmax(ll a,ll b){return a>b?a:b;} 12 13 struct son 14 { 15 int pos; 16 ll val; 17 son(int posss,ll valll) 18 { 19 pos=posss;val=valll; 20 } 21 friend bool operator < (son a,son b) 22 { 23 return a.val>b.val; 24 } 25 }; 26 int n,kk,pre[N],nxt[N]; 27 ll a[N]; 28 29 set<son> q; 30 ll ans; 31 32 int main(){ 33 34 scanf("%d%d",&n,&kk); 35 for(int i=1;i<=n;++i) 36 { 37 scanf("%lld",&a[i]); 38 pre[i]=i-1;nxt[i]=i+1; 39 q.insert(son(i,a[i])); 40 } 41 a[0]=-INF; 42 a[n+1]=-INF; 43 nxt[n+1]=n+1; 44 for(int i=1;i<=kk;++i) 45 { 46 int now=q.begin()->pos; 47 ans+=a[now]; 48 q.erase( son(now,a[now]) ); 49 a[now]=a[pre[now]]+a[nxt[now]]-a[now]; 50 q.insert(son(now,a[now])); 51 if(pre[now]!=0) q.erase( son(pre[now],a[pre[now]]) ); 52 if(nxt[now]!=n+1) q.erase( son(nxt[now],a[nxt[now]]) ); 53 54 nxt[pre[pre[now]]]=now; 55 pre[nxt[nxt[now]]]=now; 56 pre[now]=pre[pre[now]]; 57 nxt[now]=nxt[nxt[now]]; 58 } 59 60 cout<<ans; 61 //while(1); 62 return 0; 63 }
以上是关于2017.8.7 联考 就 贪心(有反悔策略)的主要内容,如果未能解决你的问题,请参考以下文章
51nod 1476 括号序列的最小代价 (括号题套路+反悔贪心)
2017.8.7 联考水题 Passward kmp/hash 字符串