洛谷 1327数列排序
题目链接
给定一个无序数列,应该交换几次就能变成一个有序数列,首先要保存这个两个一样的无序数列,然后一个数组给它排序,两个数组进行比较,如果数组元素不一致,就交换次数加一,进行调换,调换的时候,我们要知道跟数组里的哪个元素进行调换,所以我们还需要知道在有序数组里在这个位置的元素的下标,所以我们需要一个STL容器map,这跟普通数组有什么区别呢,map比普通数组的容量更大,数组不能超过1e9,但是map可以。
#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const int N=1e5+5;
map<int,int>F;
int a[N],b[N];
int n,m,ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i],F[a[i]]=i;
sort(b+1,b+n+1);
for(int i=1;i<=n;i++)
if(a[i]!=b[i]){
ans++;
int x=F[b[i]];
F[a[i]]=x;
a[x]=a[i];
}
printf("%d",ans);
}
洛谷 1308统计单词数
题目链接
注意点:
1、字符串有空格,怎么输入,用gets函数;
2、怎么不区分大小写,要么全变成大写,要么全变成小写;
3、怎么匹配,这里要求的是匹配单词,所以从有空格的地方的前一个单词开始匹配,不要从有空格的后面,因为这样第一个单词就能匹配上的时候会忽略。
#include<iostream>
#include<cstring>
using namespace std;
#include <cctype>
#include <cstdio>
void strlower (char *a) {//手写函数,将大写字母转换成小写字母
for(int i = 0; a[i]; i ++ ) {
if(isupper(a[i])) a[i] = tolower(a[i]);//isupper是判断是否是大写字母的系统函数,tolower是将其转换成小写字母的函数
}
}
char a[11];
char s[100001];
int ans;
int main(){
gets(a);
gets(s);
int len=strlen(a);
strcat(a," ");
strcat(s," ");//在ab后各加一个" ",减小配对的难度
strlower(a);
strlower(s);
int i, n=0, j, ss=0, k, rec;
for(i=0;s[i]!='\0';i++){
if (s[i] == ' ') {
ans=1;
for (j = n,k = 0; j <= i, a[k] != '\0'; j++, k++) {
if(s[j] == a[k]) {
ans*=1;//用s来记录各个位能否对应,如果结果是1就正确,一位不对s就变成0
} else {
ans*=0;
}
}
if (ans == 1) {
ss++; //如果每次都对就增加符合的次数
}
if (ss == 1 && ans==1) {
rec = n; //记录第一次符合的位数
}
n=i;
n++;
}
}
if(!ss){
cout<<-1<<endl;return 0;
}
cout<<ss<<" "<<rec<<endl;
return 0;
}
洛谷 1328生活大爆炸版石头剪刀布
注意:
1、得分表的到来,罚分记为0,平分记为0,得分记为1,阴影部分由非阴影部分得来,如甲出蜥蜴人,乙出石头,可由甲出石头,乙出蜥蜴人得出,甲对乙的结果是输,为什么罚分为0,不为-1,因为我们要计算的是他们两人的得分。
2、为什么要取余,因为当n大于aa和bb的时候,我们要得到的数组下标不能大于aa和bb。
#include<iostream>
using namespace std;
int n, aa, bb, a[300], b[300], numa, numb;
int book[5][5] = {{0,0,1,1,0},{1,0,0,1,0},{0,1,0,0,1},{0,0,1,0,1},{1,1,0,0,0}}; //得分表的处理
int main(){
cin>>n>>aa>>bb;
for(int i=0;i<aa;i++){
cin>>a[i];
}
for(int i=0;i<bb;i++){
cin>>b[i];
}
for(int i = 0; i < n; i++)
{
numa += book[a[i % aa]][b[i % bb]]; //周期循环
numb += book[b[i % bb]][a[i % aa]];
}
cout << numa << " " << numb << endl;
return 0;
}
洛谷 P1334 瑞瑞的木板 P1090 合并果子
瑞瑞的木板
合并果子
这里需要讲讲什么是优先队列
普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。
首先要包含头文件#include, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队。
优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。
和队列基本操作相同:
top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。
当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆。
一般是:
//升序队列,小顶堆
priority_queue <int,vector<int>,greater<int> > q;
//降序队列,大顶堆
priority_queue <int,vector<int>,less<int> >q;
//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
这上面两个题目所用的代码一样,都是用到了升序队列,跟普通队列不同的就是优先队列对队列里的元素进行了排序。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
priority_queue<ll,vector<ll>,greater<ll> > a;//这里直接调用优先队列
int main(){
long long ans=0,n,t;//ans注意要开long long,不然会爆
scanf("%lld",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&t);
a.push(t);
}
for(int i=1;i<=n-1;i++){
int c,d;
c=a.top();
//cout<<c<<" ";
a.pop();
d=a.top();
//cout<<d<<endl;
a.pop();//每次取最小的两个数
ans+=c+d;//加上能量
a.push(c+d);
}//和合并果子一样
printf("%lld",ans);
return 0;
}
这周就整理了这些啦,希望对看到的你有所帮助!