(noip 模拟 flower 种花)<贪心+后悔>
2017-09-09 13:14
411 查看
Problem
有n个带权点围成一圈,取出m个,使取出点的权值和最大,且任意两个相邻点不会都被取到Solution
如果选第i个点,ans+=val[i]如果选第i个点左右两个点,ans+=val[l](前驱)+val[r](后继)
但是这两种方案哪个更优是无法确定的
把某个点的权值取出后,将它的权值赋为val[l]+val[r]-val[i]
这样以后如果在选这个点,+val-val相互抵消,实际上ans+=val[l]+val[r],相当于选第i个点的前驱和后继
这里的前驱后继并不是i-1和i+1,因为从队列里取出i后,就会让i出的权值改为val[l]+val[r]-val[i],之后必须把val[l]和val[r]都赋为0,才不会重复
因此需要改前驱和后继,具体看代码
Code
// by spli #include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<queue> using namespace std; const int N=3010; int n,m; int a ; int L ,R ; bool vis ; struct node{ int k; }; priority_queue<node> q; int ans=0; bool operator <(const node &x,const node &y){ return a[x.k]<a[y.k]; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",&a[i]); for(int i=1;i<=n;++i) q.push((node){i}); L[1]=n;R[1]=2; L =n-1;R =1; for(int i=2;i<=n-1;++i) L[i]=i-1,R[i]=i+1; while(m--){ node f=q.top(); q.pop(); while(vis[f.k]){ f=q.top(); q.pop(); } ans+=a[f.k]; a[f.k]=a[L[f.k]]+a[R[f.k]]-a[f.k]; vis[L[f.k]]=1; vis[R[f.k]]=1; L[f.k]=L[L[f.k]]; R[f.k]=R[R[f.k]]; R[L[f.k]]=f.k; L[R[f.k]]=f.k; q.push((node){f.k}); } cout<<ans; return 0; }
相关文章推荐
- (noip 模拟 allonsy)<概率+组合数学>
- (noip 模拟 染色)<树形DP>
- jzoj4726. 【NOIP2016提高A组模拟8.22】种花 贪心+堆
- (noip 模拟 Matrix)<逃避矩阵乘法的好方法#滑稽>
- (洛谷 1632 点的移动 noip 模拟 tower)<脑洞题>
- 【jzoj4726】【NOIP2016提高A组模拟8.22】【种花】【可撤销贪心】
- (vijos 1892 noip 模拟 tree)<树形DP求树的最大匹配及方案数>
- (noip 2015 斗地主)<搜索+贪心>
- (noip 模拟 gift)<丧病背包>
- (noip 模拟 Fseq)<转化为多重集合的排列问题>
- JZOJ4726【NOIP2016提高A组模拟8.22】种花 增加改错机制的后贪心
- JZOJ4726. 【NOIP2016提高A组模拟8.22】种花(2017.8DP&贪心专题)
- ZOJ 3939The Lucky Week<模拟/暴力>
- Android实战简易教程<五十六>(模拟美团客户端进度提示框)
- JZOJ 4726. 【NOIP2016提高A组模拟8.22】种花
- Java【多线程知识总结(10)】线程通信之wait()与notify()的运用--模拟指挥官指挥2个连队交替轰炸战区<另外的写法>
- NOIP模拟 朋友(快排+贪心)
- 反射模拟--List<User>users-----JSON
- 【贪心】CODE[VS] 1063 NOIP2004普及组-合并果子 (刷题记录(模拟+优先队列))
- <模拟电子学习1>Multisim 12.0 结构和仿真51最小的单芯片系统