(家常废话)
今天是第三天,刚从搜索的大坑里跳出来,老师早上还说着我们能放松放松,结果……哎,又过了一个愚人节。不说了,回归主题,愚人节主题的数据结构,首先,分以下几种:链表,栈,队列,堆。
NO.1链表
特点:
1. 数据存在数组中。
2. 对于每一个数据要记录后一个元素的下标位置(前面也可以)。
3. 要记录第一个元素(也可以记录最后一个)数据所在的数组下标。
操作(原因就不解释了)
遍历
For(int i=first[10];i<=0;i=next[i])
Cout<<d[i]<<endl;
插入
Next[px]=next[pa];
Next[pa]=px;
删除
Next[pa]=next[px];
Next[px]=0;
NO.2栈
特点:
1. 存在数组中,数组的大小为栈的大小
2. 用一个变量top记录栈顶数据的下标。
3. 栈空时top=0,栈满时top=MAXSIZE-1,通过s[top]来访问栈顶,入栈{++top; s[top]=x;},出栈- -top.
Eg1:火车出栈
题目大意:火车从A入站台,从B出站台,顺序为1~·n,给定一出站台顺序,判断是否有可能。
分析: 用栈模拟过程,把站台看成栈,按1~n顺序遍历火车原先顺序,先入栈,如果栈顶的火车编号和所给出的元素编号相同,则出栈,否则一直入栈。
(不符代码)
Eg2:表达式求值
题目大意:给你一个只有加法和乘法的表达式,计算结果。
分析:使用两个栈,一个存数字,一个存符号,如果是符号,并且优先级大于栈顶符号,则压入栈中,否则取出符号栈栈顶元素,并取出数字栈栈顶的两数字运算,再存回栈,重复以上步骤直至栈为空或大于栈顶符号。
NO.3队列
特点:
1. 存在数组中,数组大小为队列容量。
2. 用head和tail记录队列头数据的下标-1和队尾的数据下标。
3. 队空时head=tail. 队满时tail=MAXSIZE-1(与head和tail无关)。访问队首Q[MAXSIZE+1],新元素入队{++tail,q[tail]=x},出队 ++head;
普通队列使用过的部分将会被废弃,浪费太大,所以改用循环队列。
普通队列 | 循环队列 | |
队空 | head=tail | head=tail |
队满 | tail=MAXSIZE-1 | (tail+1)%MAXSIZE=head |
队尾插入 | ++tail; q[tail]=x; | tail=(tail+1)%MAXSIZE; q[tail]=x; |
对头出队 | ++head; | head=(head+1)%MAXSIZE |
实际容量 | tail-head | (MAXSIZE+tail-head)%MAXSIZE |
//双端队列:队头队尾可随意进出队(队头进队++head;队头出列- -head;队尾入队++tail;队尾出队- -tail).
Eg:贪吃
题目大意:有n个零食,营养价值为w,可正可负,零食需要连续的一段,他至少要选择min种,最多又不能超过max种,问他最多能获得多少营养值.
分析:先求出前缀和。假设零食一个个进入视线,每加入一个零食,i-max以前的就会没用,出队;i-min以后的不能用,暂时不能入队,让s[i-min]大于队列中所有的元素,否则队列元素出栈,这样队头的s肯定是可取范围内最小的s,也就使得s[i]-s[head]最大,即最后一个零食为i时最大营养值,每个零食,s[i]-s[head]的最大值即所求。
//单调队列:解决长度限定内的区间的最大最小值队首队尾都可以出队。
考题在这儿:
木材加工
题目大意:有一块大木板,现在要按给定的长度截成几块小木板,每次截都会付出相应的代价即为所截木板的长度,给定木板总数和各个小木板的长度,求最小代价和。
分析:与合并果子类似,但是……样例不是这个意思啊,我根据样例做了,咳咳,60,回头来看,规律找错了,正解是所需要的长度和*2后减去所要截的最大长度。改正后代码如下:
#include <bits/stdc++.h>
using namespace std;
int sum,maxx,n,x;
long long s;
int main()
{
//freopen("wood.in","r",stdin);
//freopen("wood.out","w",stdout);
sum=0;maxx=-10000000;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
sum+=x;//累加长度和
if (x>maxx) maxx=x;//寻找最大值
}
s=sum*2-maxx;//计算,长度和*2-最大值
cout<<s<<endl;
//fclose(stdin);
//fclose(stdout);
return 0;
}