吞噬算法
来源:互联网 发布:骨科空心钉 知乎 编辑:程序博客网 时间:2024/06/10 14:37
O(kn)
咳咳,这是“力量”同学乱搞搞出来的吞噬算法,其主旨就是吃。。。(话说多少算法不是乱搞搞出来的)
题目描述
【题目描述】
WZK 最近收到了一个任务。
给出一个 n 个数的序列,为 A0,A1,„„,An-1,循环移动 k 位之后,这个序列就变 成了 Ak,Ak+1,„„,An-1,A0,A1,„„,Ak-1。一种优秀的循环移动是,对于任意的 前 i(1<=i<=n)项和都满足不小于零。请给出这个序列优秀循环移动的个数。
这道题目当然是很简单啦,但是 WZK 忙着吃小浣熊干脆面,手上油油的写不了程序,于是就麻烦你啦!如果能做到满分,他就会考虑请你吃一包哦~
【输入格式】
第一行一个整数 n(1 <= n <= 10^6),表示有 n 个数。
第二行 n 个整数,Ai(-1000 <= Ai <= 1000)表示给出的第 i 个数。
【输出格式】 一行一个整数,表示优秀循环移动的个数。
【样例输入】
one:
3
2 2 1
two:
4
-3 5 1 2
【样例输出】
one:
3
two:
2
然后luogu出在了月赛题里
uim在公司里面当秘书,现在有n条消息要告知老板。每条消息有一个好坏度,这会影响老板的心情。告知完一条消息后,老板的心情等于之前老板的心情加上这条消息的好坏度。最开始老板的心情是0,一旦老板心情到了0以下就会勃然大怒,炒了uim的鱿鱼。
uim为了不被炒,知道了了这些消息(已经按时间的发生顺序进行了排列)的好坏度,希望研究如何不让老板发怒。
uim必须按照时间的发生顺序逐条将消息告知给老板。不过uim可以使用一种叫“倒叙”的手法,例如有n条消息,小a可以从k,k+1,k+2…n,1,2…k-1这种顺序通报。
他希望知道,有多少个k,从k开始通报到n然后从1通报到k-1可以让老板不发怒。
基础思路
简单看来这就是一个环,选能走下来的位数和一直不小于0的数。。。样例和没有没区别。然而环,单调队列神马的都太复杂了,现在请参考吞噬算法——
产生随机数 7,1,-5,2,-3(n=5)
首先,从第一位开始扫到第一个负数-5,然后用-5 吃掉前一个数1 ,于是变成了7, -4 ,2,-3
看来,一个1 满足不了-5 的胃口,于是接着往下吃 3 ,2,-3 .
呃,-4 撑死了……那就接着往下揍,找到了-3 ,-3 吃了2 ,变成3,-1,再往前吃,就成了2,好了,只剩下正数了,于是输出正数的个数 1。
P版代码——
var n,s,i:longint; a:array[1..1000005] of integer; b:array[1..1000005] of longint;begin assign(input,'sum.in'); assign(output,'sum.out'); reset(input); rewrite(output); readln(n); for i:=1 to n do read(a[i]); i:=0; while i<n do begin inc(i); inc(s); b[s]:=a[i]; if a[i]<0 then begin while (b[s]<0) and (s>1) do begin dec(s); b[s]:=b[s]+b[s+1]; b[s+1]:=0; end; while b[s]<0 do begin b[s]:=b[s]+a[n]; dec(n); if n<i then begin writeln(0); close(input); close(output); end; end; end end; writeln(s); close(input); close(output);end.
通俗解释
那么,通俗点说呢,首先找到-5,要想成立,-5前面的和必须比0大,于是-5必须在1后面。同理,7,1,-5这个顺序不能打乱。于是推到最后,就行了。
栈实现
这里是用栈来实现
另一种解释
然后另一组随机数据-3,5,1,2 怎么办?
依然很简单。先将a【1】与a【4】吞噬了(a【i】,a【n】) 然后n– 直到a【1】 再push
#include<stack>#include<iostream>using namespace std;int a[1000000+2],n;stack<int>s;int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) if(a[i]>0) s.push(a[i]); else{ while(!s.empty()&&a[i]<0){ int t=s.top(); a[i]+=t; s.pop(); } if(a[i]<0)while(a[i]<0&&n>i) a[i]+=a[n--]; if(a[i]<0){ cout<<0; return 0; } s.push(a[i]); } cout<<s.size(); return 0;}
所有元素最多读一次,进栈一次,出栈一次,最少读一次,进栈一次。这个时间复杂度可以处理任何数据(时间复杂度再高就读不进了)。故此算法时间复杂度(kn)k属于[2,3)。
- 吞噬算法
- 吞噬星空
- cocos2dx吞噬
- rqnoj-156-吞噬比赛-最长上升子序列O(nlog(n))算法
- 自我吞噬的新作用:异体吞噬
- 暗之魔法-吞噬
- gtk-gnash 吞噬CPU
- 软件正在吞噬整个世界
- 软件正在吞噬整个世界
- UILayer 中的 吞噬
- 软件吞噬软件开发
- 膳殖右吞噬坪浇窘郊步来母盏右骋
- 奥抛吞噬盒瓜瓜豪垢钥辰汹瞻瓮乐
- 软件正在吞噬整个世界
- 吞噬世界的软件
- 【动态规划】【RQ156】吞噬比赛
- 新游戏《火焰吞噬》上线
- 谁在吞噬着这个世界
- 【软工文档】 之 文档总结
- 中秋啦
- 9.27
- RDO部署多节点OpenStack Havana(OVS+GRE)
- iOS开发:GET与POST接口网络请求以及对AFNetworking的二次封装
- 吞噬算法
- 倒置链表
- noip2010 机器翻译 (模拟)
- 详细设计说明书——机房收费系统
- 在C/C++中调用python的简单笔记part 1
- 对实训以及实训后的看法
- KissXML解析
- 3.3.5 使用HtmlDiff对象
- HDU 25919 新生晚会(水题组合问题)