A - 前m大的数
这题我直接暴力解题,数字两两结合,排序输出,废话不多说了,先上代码
#include<iostream>
#include<algorithm>
using namespace std;
int sum[4500000],a[10086]; **//N(N<=3000),N*(N-1)/2,可以得到两项和的数组,粗略算一下这个数够用了**
int main()
{
int n,m,k;
while(cin>>n>>m)
{
for(int i=0;i<n;i++)
cin>>a[i];
k=0; **//注意,每输入一次,计算N*(N-1)/2要清零**
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
sum[k]=a[i]+a[j]; ** //暴力求和**
k++;
}
}
sort(sum,sum+k); ** //排序sort比较快**
for(int i=k-1;i>k-m;i--)
cout<<sum[i]<<" ";
cout<<sum[k-m]<<endl; ** //我特意瞅了一眼输出,果然有坑,最后没空格**
}B - 稳定排序
如果对于数组中出现的任意a[i],aj,其中a[i]==a[j],在进行排序以后a[i]一定出现在a[j]之前,则认为该排序是稳定的,注意排序方式。
对于每组数据,如果算法是正确并且稳定的,就在一行里面输出"Right"。如果算法是正确的但不是稳定的,就在一行里面输出"Not Stable",并且在下面输出正确稳定排序的列表,格式同输入。如果该算法是错误的,就在一行里面输出"Error",并且在下面输出正确稳定排序的列表,格式同输入。
结构体储存数据,排序,对比,判断输出。
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct s{
int score;
int que;
char name[55];
}a[360],b[360];
int cmp(s x,s y)
{
return x.score!=y.score?x.score>y.score:x.que<y.que; //排序方式,稳定排序处理
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(a,0,sizeof(a)); //清空数据
memset(b,0,sizeof(b));
for(int i=0;i<n;i++)
{
scanf("%s%d",&a[i].name,&a[i].score);
a[i].que=i; //位置序号记录
}
sort(a,a+n,cmp);
int f1=1,f2=1;
for(int i=0;i<n;i++)
{
scanf("%s%d",&b[i].name,&b[i].score);
if(strcmp(a[i].name,b[i].name)!=0) f1=0; //姓名比较
if(a[i].score!=b[i].score) f2=0; //分数比较
}
if(f1+f2==2) printf("Right\n"); //判断阶段
else if(f1==0&&f2==1)
{
printf("Not Stable\n");
for(int i=0;i<n;i++)
{
printf("%s %d\n",a[i].name,a[i].score);
}
}
else
{
printf("Error\n");
for(int i=0;i<n;i++)
{
printf("%s %d\n",a[i].name,a[i].score);
}
}
}
return 0;
}C-开门人和关门人
比较时间来输出开关门人的证件号码,用结构体可以实现,由于时间输入的格式,我觉得一般直接比较数字的方法行不通,利用char[]和strcmp()函数进行比较,比较合适。
#include<bits/stdc++.h>
using namespace std;
struct
{
char num[1000];
char tim1[1000];
char tim2[1000];
}st[1000]; //结构体设定好,证件号,出入时间
int main()
{
int t,n,max,min;
cin>>t;
while(t--)
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>st[i].num;
cin>>st[i].tim1;
cin>>st[i].tim2;
}
min=0,max=0;
for(int i=0;i<n;i++)
{
if(strcmp(st[min].tim1,st[i].tim1)>0) //注意strcmp()实现比较时间。
min=i;
if(strcmp(st[max].tim2,st[i].tim2)<0)
max=i;
}
cout<<st[min].num<<" "<<st[max].num<<endl;
}
return 0;
}D - EXCEL排序
先读一遍题,发现题目中输入数据和题干,我觉得结构体妥妥的,然后比较一下并排序,开始注意排序
当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3 时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。
接下来码代码就行了,肝
#include<bits/stdc++.h.>
using namespace std;
struct s{
char num[10];
char name[10];
int sorce;
}t[100010];
bool cmp1(s a,s b){ //学号递增排序
return strcmp(a.num,b.num)<0;
}
bool cmp2(s a,s b){ //按照姓名的非递减字典序排序
if(strcmp(a.name,b.name)) return strcmp(a.name,b.name)<0;
else return strcmp(a.num,b.num)<0;
}
bool cmp3(s a,s b){ //按成绩的非递减排序
if(a.sorce!=b.sorce) return a.sorce<b.sorce;
else return strcmp(a.num,b.num)<0;
}
int main(){
int m,n,count=0;
while(scanf("%d%d",&m,&n)!=EOF){
if(m==0) break;
int i;
for(i=0;i<m;i++){
scanf("%s %s %d",&t[i].num,&t[i].name,&t[i].sorce);
}
switch(n){ //选择数,试试switch比if看起来整洁点
case 1:sort(t,t+m,cmp1);break;
case 2:sort(t,t+m,cmp2);break;
case 3:sort(t,t+m,cmp3);break;
}
printf("Case %d:\n",++count); //注意输出格式
for(i=0;i<m;i++){
printf("%s %s %d\n",t[i].num,t[i].name,t[i].sorce);
}
}
return 0;
}
E-{A}+{B}
考察set函数,把两个集合元素插入一个集合,去重,输出,上代码
#include<iostream>
#include<set>
using namespace std;
set<int>se;
int main()
{
int n,m;
while(cin>>n>>m)
{
n=n+m; //两个集合的元素书混一起,方便插入到同一个集合进行去重
se.clear(); //注意清空上一次集合内部残存元素
while(n--)
{
int a;
cin>>a;
se.insert(a);
}
int flag=0; //下文空格输出有限制,最后一个元素输出不要空格
set<int>::iterator it;
for(it=se.begin();it!=se.end();it++)
{
if(flag!=0) //回收flag
cout<<" ";
cout<<*it;
flag++;
}
cout<<endl;
}
return 0;
}F - 水果
多组数据组合,考虑到结构体,水果数,考虑到map去计数,组合一下就出来了
上代码
#include<iostream>
#include<map>
#include<string>
using namespace std;
struct my{
map<string,int>myma; //结构体套map,组合地名。水果名,数字便于输出
};
int main()
{
map<string,my>ma;
map<string,my>::iterator it; //迭代器
map<string,int>::iterator mymait;
string fruit,place;
int num;
int n,t;
cin>>t;
while(t--)
{
ma.clear();
cin>>n;
while(n--)
{
cin>>fruit>>place>>num;
ma[place].myma[fruit]+=num;
}
for(it=ma.begin();it!=ma.end();it++)
{
cout<<it->first<<endl;
for(mymait=it->second.myma.begin();mymait!=it->second.myma.end();mymait++) //这个结构体套map有点绕,总之mymait->first是水果名,mymait->second是水果数
{
cout<<" |----"<<mymait->first<<"("<<mymait->second<<")"<<"\n";
}
}
if(t!=0)cout<<"\n"; //注意大坑,最后\n要看好结构
}
return 0;
}G - 不重复数字
用map函数对每次输入进行检测,如果重复了就不输出,不重复就输出,上代码
#include<bits/stdc++.h>
using namespace std;
map<int,int>ma;
int main()
{
long long int t;
scanf("%lld",&t); //scanf,printf,快一点
while(t--)
{
long long int n,a,flag=0;
scanf("%lld",&n);
ma.clear();
for(long long int i=0;i<n;i++)
{
scanf("%lld",&a);
if(ma[a]==0) //检测是否重复出现过
{
if(flag!=0) //注意输出格式,最后一个不输出空格,此处回收flag
printf(" ");
printf("%lld",a);
}
flag++;
ma[a]++; //数出数字出现次数
}
printf("\n");
}
return 0;
}H - 表达式括号匹配
检测(和)两个字符是否出现次数相同,签到题,直接上代码
#include<bits/stdc++.h>
using namespace std;
map<int,int>ma;
int main()
{
char s[3000];
int n=0,m=0;
cin>>s;
for(int i=0;i<strlen(s);i++)
{
if(s[i]=='(')
n++;
if(s[i]==')')
m++;
}
if(n==m)
cout<<"YES";
else
cout<<"NO";
}I - 合并果子
priority_queue和queue不同的就在于我们可以自定义其中数据的优先级,让优先级高的排在队列前面,优先出队,每次把最小代价的排出来,然后合并,用priority_queue岂不美哉,每一次消耗最小从而得出最优解,废话不多说上代码
#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int>> que;
int main()
{
int t;
cin>>t;
while(t--)
{
int n,a;
cin>>n;
while(que.size()) que.pop(); //清空上一次的参与元素
while(n--)
{
cin>>a;
que.push(a); //把元素加到priority_queue
}
long long int sum=0; //和的话就大些比较好,long long 稳点
while(que.size()>=2) //保证最后是两堆果子
{
int x=que.top();que.pop(); //排出最小
int y=que.top();que.pop(); //第二小
sum+=x+y; //总消耗
que.push(x+y); //合并后的果子堆别忘了也要计入
}
cout<<sum<<endl;
}
return 0;
} J - Covered Points Count
建立一个数组,每读一条线段进来,就把线段上的点都加1,最后遍历数组计算出值,
#include<iostream>
#include<map>
using namespace std;
typedef long long ll;
const int N=2e5+5;
map<ll,int>ma;
map<ll,int>::iterator it;
ll cnt[N];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
ll l,r;
cin>>l>>r;
ma[l]++; //原则,头部加,末尾后退一步减
ma[r+1]--;
}
ll last=0; //当前区间起点
int ans=0;
for(it=ma.begin();it!=ma.end();it++) //遍历了
{
if(it==ma.begin())
{
last=it->first;
ans+=it->second; //此点覆盖
continue;
}
cnt[ans]+=it->first-last;
last=it->first;
ans+=it->second;
}
for(int i=1;i<=n;i++)
{
cout<<cnt[i];
if(i==n)
cout<<"\n";
else
cout<<" ";
}
return 0;
} K - Ignatius and the Princess IV
计算出现次数,map是个很好的选择,当然不用STL也可以,不过还是熟练一下STL更好,上代码
#include<iostream>
#include<map>
using namespace std;
map<int,int>ma;
int main()
{
int n;
while(cin>>n)
{
ma.clear(); //记得清空参与元素
for(int i=0;i<n;i++)
{
int a;
cin>>a;
ma[a]++; //计算出现次数
}
int flag=0; //因为要控制输出输出次数
map<int,int>::iterator it;
for(it=ma.begin();it!=ma.end();it++)
{
int t=it->second;
if(t>=(n+1)/2&&flag==0)
{
int q=it->first;
cout<<q<<endl;
flag--;
}
}
}
return 0;
} L - Stones
重载运算符
<返回类型说明符> operator <运算符符号>(<参数表>) { <函数体> }
优先队列应用,上代码吧
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int>mp;
struct cmp
{
bool operator()(mp a,mp b) //first表位置,second表距离
{
if(a.first==b.first) //距离从小到大排序
return a.second>b.second;
return a.first>b.first;
}
}
priority_queue<mp,vector<mp>,cmp>que;
int main()
{ //优先队列插入
int t,n,a,b;
cin>>t;
while(t--)
{
cin>>n;
while(!que.empty())que.pop(); //清空残余元素
for(int i=0;i<n;i++)
{
cin>>a>>b;
que.push(mp(a,b))
}
int num=1;
mp next;
while(!que.empty())
{
next=que.top();
que.pop();
if(num&1)que.push(mp(next.first+next.second,next.second));
num++;
}
printf("%d\n",next.first);
}
return 0;
}M - SnowWolf's Wine Shop
multiset是<set>库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数是有序的,而且序列中可以存在重复的数。利用这个特性,存酒。</set>
#include<stdio.h>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
int t,a,b,c,x,cas=1;
scanf("%d",&t);
while(t--)
{
multiset<int > wine;
wine.clear(); //记得清空残余量
scanf("%d%d%d",&a,&b,&c);
printf("Case %d:\n",cas++);
while(a--)
{
scanf("%d",&x);
wine.insert(x); //输入
}
while(b--)
{
scanf("%d",&x);
multiset<int >::iterator t=wine.lower_bound(x);
if(t==wine.end()||*t-x>c)printf("-1\n");
else
{
printf("%d\n",*t);
wine.erase(t); //记得清除
}
}
}
return 0;
}N - Alice, Bob and Candies
两个小朋友从两边吃糖,吃的一方要比上一次一方吃的多,求次数与双方吃糖数,模拟两方吃糖就行了
上代码吧。
#include <iostream>
using namespace std;
int const N=1e5+5;
int c[N]; //存糖
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>c[i];
n--;
int x=0,y=0,last=0,num=0; //last存上次吃糖数,num是次数,x和y是两个小朋友吃糖数
for(int i=0;i<=n;)
{
num++;
int sum=c[i++];
while(sum<=last&&i<=n) sum+=c[i++]; //模拟吃糖
x+=sum;
last=sum;
if(i>n) break; //记得检测吃的堆数
num++;
sum=c[n--];
while(sum<=last&&i<=n) sum+=c[n--];
y+=sum;
last=sum;
}
cout<<num<<" "<<x<<" "<<y<<endl;
}
return 0;
}O - Special Elements
给定n个数,如果a[i]=sum(a[l-r])(1<=l<r<=n),那么称a[i]为一个特殊数,求这n个数中特殊数的个数。
然后将a数组前缀和处理。
枚举a[]所有区间的和,同时进行查询a[]中原来是否有这个数,如果有则加上这个数的个数即可。
#include <iostream>
#include <cstring>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
int T, n, x, mx, sum[8848]={0}, cnt[8848], tmp, res;
int main(){
ios;
cin>>T;
while (T --){
res=0, mx=0;
memset(cnt, 0, sizeof(cnt));
scanf("%d",&n);
for (int i= 1;i<=n;i++){
scanf("%d",&x);
mx=max(mx,x);
sum[i]=sum[i-1]+x;
cnt[x]++;
}
for (int i=1; i < n; i ++){
for (int j=i+1; j <=n ; j ++){
tmp=sum[j]-sum[i - 1];
if(tmp>mx) break;
if (tmp<8848&&cnt[tmp] != 0) {
res+=cnt[tmp];
cnt[tmp] = 0;
}
}
}
cout<<res<<"\n";
}
return 0;
}
P - Max Sum
求最大的连续子段和,求出并输出该子段和的起始位置,记一个最大和summax,使其不断与前j个数的和比较若sum[j]>summax并记录开始与结束的位置,则使summax=sum[i];若sum[i]<0,则sum[i]=0并记录此时的位置为起始位置;此后不断循环最终得到所求结果。注意起始位置的记录。
#include<iostream>
using namespace std;
int main()
{
int n,t;
int a[100860];
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
int k=1,st=0,en=0,summax=-3000,sum=0; //记录点,最大和数
scanf("%d",&n);
for(int j=0;j<n;j++)
{
scanf("%d",&a[j]);
}
for(int j=0;j<n;j++) //不断比较阶段,注意记录起始点
{
sum+=a[j];
if(sum>summax)
{
summax=sum;
st=k;
en=j+1;
}
if(sum<0)
{
sum=0;
k=j+2;
}
}
printf("Case %d:\n%d %d %d\n",i,summax,st,en);
if(i!=t)
cout<<"\n";
}
return 0;
}
京公网安备 11010502036488号