今天总共写了三道题
两道 单调队列 一道最优队列
—————————————————————————————————————————————————————————————————————————————
给你一个长度为 N 的数组,一个长为 K 的滑动的窗体从最左移至最右端,
你只能见到窗口的K个数,每次窗体向右移动一位,如下表:
你的任务是找出窗口在各位置时的 max value,min value.
用单调队列维护最小值 和 最大值
当队列不为空 且 出现逆序 则队尾出队 当前值入队
当队列的大于了窗口 则对头出队
我直接写了一个通用的程序 就省得开两个队列 减少了好多代码量
#include<iostream> #include<cstdio> using namespace std; const int N=1000000; int n,k,num[N+10],q[N+10]; void work(int a) { int head=1,tail=0; for(int i=1;i<=n;i++) { while((head<=tail)&&((!a&&num[i]<=num[q[tail]])||(a&&num[i]>=num[q[tail]]))) tail--; q[++tail]=i; while(head<=tail&&q[tail]-q[head]>=k) head++; if(i>=k) printf("%d ",num[q[head]]); } } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&num[i]); work(0); printf("\n"); work(1); return 0; }
—————————————————————————————————————————————————————————————————————————————经过几个月辛勤的工作,FJ决定让奶牛放假。假期可以在1…N天内任意选择一段(需要连续),每一天都有一个享受指数W。但是奶牛的要求非常苛刻,假期不能短于P天,否则奶牛不能得到足够的休息;假期也不能超过Q天,否则奶牛会玩的腻烦。FJ想知道奶牛们能获得的最大享受指数。
这道题思路上 不是那么难 直接上代码 基本和第一题神似
—————————————————————————————————————————————————————————————————————————————#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<cmath> using namespace std; long long num[10000000]; long long q[10000002]; long long head=1,tail=1; long long maxx=-1000000000; int main() { //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); long long n,d,c; cin>>n>>d>>c; long long w; long long nn=0; for(int i=1;i<=n;i++) { cin>>w; nn+=w; num[i]=nn; } q[head]=1; for(int i=1;i<=n;i++) { if(i-q[head]>c-d)head++; long long xx=i+d; while(num[i]<=num[q[tail]]&&tail>=head) tail--; q[++tail]=i; long long sum; if(xx<=n) { sum=num[xx]-num[q[head]]; if(sum>maxx)maxx=sum; } } cout<<maxx<<endl; return 0; }
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
这道题是个优先队列 思路很简单 就是 建立一个以最小为优先的优先队列
然后每次 从队头取出两个元素 相加 再入队 同时求一下代价就好了
但是 我是第一次 写优先队列 所以 写的还是有点生疏 所以 耗时长了点
—————————————————————————————————————————————————————————————————————————————#include<iostream> #include<cstdio> #include<queue> #include<algorithm> using namespace std; int ans=0,n; struct node { int m; bool operator<(const node &a) const { return a.m<m; } }; int main() { priority_queue<node> Q; scanf("%d",&n); node p,q; for(int i=1;i<=n;i++) { scanf("%d",&p.m); Q.push(p); } for(int i=1;i<=n-1;i++) { p=Q.top(),Q.pop(); q=Q.top(),Q.pop(); ans+=q.m+p.m; p.m=p.m+q.m; Q.push(p); } printf("%d",ans); return 0; }
今天就到这里结束了 我感觉 队列自己学的是差不多了
明天 就是要考试了
今年的计划有变
因为我文化课不过关 所以过完年 就得在家补习文化课了 没办法去写图论
想必 过了一个寒假之后 我和他们的差距就会拉的更大了吧。。