A-前m大的数
话说这道题之前就做过,当时是因为开的数组太小,然后就错了。
解题过程
我尝试了一种新的方法(虽然是错的,但是能发现错的原因也挺好):
先把数组从大到小排序 也就是 7 6 5 4 3 2 1 从前往后加,但是忽然发现有点难以实现,比如如果按 7+6 7+5 7+4,,,,,,6+5 6+4 ,,这样循环,你会发现 7+3 < 6+5 所以还是按部就班吧,先求 和数组 再排序 记得数组要开的大一点,(5e5差不多)
具体看代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int sum[5000000];
int a[3050];
int main()
{
int n,m,i,j,k;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=0;i<n;i++)
scanf("%d",&a[i]);
k=0;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
sum[k]=a[i]+a[j];
k++;
}
}
sort(sum,sum+k);
for(i=k-1;i>k-m;i--)
printf("%d ",sum[i]);
printf("%d\n",sum[k-m]);
}
return 0;
} B - 稳定排序|| C - 开门人和关门人 || D - EXCEL排序
由于这三道题都是一个知识点 ,就合并了
这题一看就是结构体排序呀,用sort()函数排就行,重点就是自定义函数 cmp() 的定义
看代码:
//B
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn=1000;
typedef long long ll;
int n;
struct student{
string name;
int score;
int num;
}a[maxn],na[maxn];
bool cmp(student a,student b){
if(a.score != b.score) return a.score > b.score;
return a.num < b.num;
}
int main()
{
ios;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i].name>>a[i].score;
a[i].num=i;
}
sort(a,a+n,cmp);
bool flag=1,flag1=1;
for(int i=0;i<n;i++) {
cin>>na[i].name>>na[i].score;
if(a[i].score != na[i].score) flag =0;
else if(a[i].name != na[i].name) flag1 =0;
}
if(flag==0){
cout<<"Error"<<"\n";
for(int i=0;i<n;i++) cout<<a[i].name<<" "<<a[i].score<<"\n";
}
else if(flag==1 && flag1 == 0){
cout<<"Not Stable"<<endl;
for(int i=0;i<n;i++) cout<<a[i].name<<" "<<a[i].score<<"\n";
}
else if(flag && flag1) cout<<"Right"<<"\n";
}
return 0;
}
//C
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn=1e4+10;
typedef long long ll;
int n;
struct student{
string num;
string begin;
string end;
}a[maxn];
bool cmp(student a,student b){
return a.begin < b.begin;
}
bool cmp1(student a,student b){
return a.end > b.end;
}
int main()
{
ios;
int t;
cin>>n;
while(n--){
cin>>t;
for(int i=0; i<t; i++){
cin >> a[i].num >> a[i].begin >>a[i].end;
}
sort(a,a+t,cmp);
cout<<a[0].num<<" ";
sort(a,a+t,cmp1);
//if(n>=1)
cout<<a[0].num<<"\n";
//else cout<<a[0].num;
}
return 0;
}
//D
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
int n,c;
struct student{
string num;
string name;
int score;
}a[maxn];
bool cmp(student a,student b){
if(c==1){
return a.num < b.num;
}
else if(c==2){
if(a.name == b.name){
return a.num < b.num;
}
else return a.name < b.name;
}
else{
if(a.score == b.score){
return a.num < b.num;
}
else return a.score < b.score;
}
}
int main()
{
ios;
int Case=1;
while(cin>>n>>c && n){
for(int i=0; i<n; i++){
cin>>a[i].num>>a[i].name>>a[i].score;
}
sort(a,a+n,cmp);
cout<<"Case "<< Case++ <<":"<<"\n";
for(int i=0;i<n;i++) cout<<a[i].num<<" "<<a[i].name<<" "<<a[i].score<<"\n";
}
return 0;
}E - {A} + {B}
本来应该用set做的,但是 STL 用的还不熟练(虽然知道这样不好),但还是用数组做了:
解体思路:先把两个数组合并,再用unique去重(不知道unique的小伙伴点这里)
unique
感觉也挺简单的。
代码如下:
#include<iostream>
#include<algorithm>
#include<string.h>
const int MAX=1000000;
int a[MAX],b[MAX],sum[MAX];
using namespace std;
int main()
{
int n,m;
while(cin>>n>>m){
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<m;i++){
cin>>b[i];
}
int x=n+m;
for(int i=0;i<x;i++){
if(i<n){
sum[i]=a[i];
}
else{
sum[i]=b[i-n];
}
}
sort(sum,sum+x);
long long int y=unique(sum,sum+x)-sum;
for(int i=0;i<y;i++){
if(i<y-1){
cout<<sum[i]<<" ";
}
else{
cout<<sum[i];
}
}
cout<<endl;
}
return 0;F - 水果
这道题挺绕的(第一次做的时候真的不知道咋做,还好这是第二次)
这道题用map嵌套可以做,但是我还没有完全理解,就不多赘述:
我用的还是结构体排序,麻烦了点,但挺好理解的:
看代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct aa
{
char c1[81],c2[81];
int n;
}a[115];
bool camp(aa x,aa y)
{
if(strcmp(x.c1,y.c1)!=0)
return strcmp(x.c1,y.c1)<0;
return strcmp(x.c2,y.c2)<0;
}
int main ()
{
int i,t,n,sum;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
getchar();
for(i=1;i<=n;i++)
scanf("%s %s %d",a[i].c2,a[i].c1,&a[i].n);
sort(a+1,a+n+1,camp);
strcpy(a[0].c1,"00");
strcpy(a[0].c2,"00");
a[0].n=-1;
strcpy(a[n+1].c1,"00");
strcpy(a[n+1].c2,"00");
a[n+1].n=-1;
sum=a[1].n;
for(i=1;i<=n;i++)
{
if(strcmp(a[i].c1,a[i-1].c1)!=0)
{
printf("%s\n",a[i].c1);
}
if(strcmp(a[i].c1,a[i+1].c1)==0&&strcmp(a[i].c2,a[i+1].c2)==0)
{
sum+=a[i+1].n;
}
else
{
printf(" |----%s(%d)\n",a[i].c2,sum);
sum=a[i+1].n;
}
}
if(t)
printf("\n");
}
return 0;
}G - 不重复数字
思路:用map存一下,一个一个判断,重复的元素不输出就好
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#include<map>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
typedef long long ll;
const int MAXN = 50000 + 10;
int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f *= -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
map<int, int> st;
int n, x;
int main()
{
int t = read();
while(t--)
{
n = read();st.clear();bool flag = true;
for(int i=0;i<n;i++)
{
x = read();
if(st[x] == 0)
{
if(!flag) printf(" ");
printf("%d", x);
flag = false;
}
st[x] = 1;
}
printf("\n");
}
return 0;
}H - 表达式括号匹配
栈模版题:把左括号放进栈里,遇见右括号就弹出一个,如果最后栈不为空,或者栈为空了但是还有右括号,就不匹配,否则就匹配:
代码如下:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<stack>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn = 1e6+10;
typedef long long ll;
char a[3000];
int main()
{
bool flag=1;
stack <char> s;
cin>>a;
int len = strlen(a);
//cout<<len<<endl;
for(int i=0;i<len;i++){
if(s.size()){
if(a[i]==')'){
s.pop();
continue;
}
}
else{
if(a[i]==')'){
cout<<"NO";
flag=0;
break;
}
}
if(a[i]=='('){
s.push(a[i]);
}
}
if(flag==1 && !s.size()){
cout<<"YES";
}
else if(flag==1 && s.size()){
cout<<"NO";
}
return 0;
}I - 合并果子
要使耗费的精力最少,那么就要每次合并最小的两堆:
代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[1001];
int main()
{
int t;
cin>>t;
int n;
while(t--){
int sum=0;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<n-1;){
int b=0;
sort(a+i,a+n);
b=a[i]+a[i+1];
sum+=b;
a[++i]=b;
//cout<<sum<<endl;
}
cout<<sum<<endl;
}
return 0;
}K - Ignatius and the Princess IV
这道题是求中位数把,一个数出现了(n+1)/2次 超过一半了,中位数肯定有它
看代码:
//#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int n;
int a[maxn];
int main()
{
ios;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
if(n & 1){
cout<<a[(n+1)/2]<<"\n";
}
else cout<<(a[n/2]+a[n/2+1])/2<<"\n";
}
return 0;
}M - SnowWolf's Wine Shop
这道题用multiset做,里面有一个lowerbound()函数返回集合里第一个大于等于参数元素的位置(返回值是地址,第一次就卡在了这里,学习的时候还是要认真一些)
那思路不就是:按照顺序,如果酒价和客人付的钱相差不超过某一个值,输出这个值,否则输出-1;
代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int a,b,c,m;
int main()
{
ios;
int t,j=1;
cin>>t;
while(t--){
multiset<int> w;
w.clear();
cin>>a>>b>>c;
cout<<"Case "<<j++<<":"<<"\n";
for(int i=0 ; i<a; i++){
cin>>m;
w.insert(m);
}
for(int i=0; i<b; i++){
cin>>m;
if(w.lower_bound(m)==w.end()||*w.lower_bound(m)-m > c){
cout<<"-1"<<"\n";
}
else{
cout<<*w.lower_bound(m)<<"\n";
w.erase(w.lower_bound(m));
}
}
}
return 0;
}N - Alice, Bob and Candies
一直又都点讨厌这种模拟题,真的好麻烦
理解都写在代码的注释上了,看看吧,
//#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int const N=2e5+5;
int c[N];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&c[i]);
n--;
int a=0,b=0,u=0,cnt=0; //a存Alice吃的糖数,b存储Bob吃的糖数
//u存储上一次某人吃的糖数,cnt表示轮数。
for(int i=0;i<=n;)
{
cnt++;
int sum=c[i++]; //sum表示这次某人吃的糖数
while(sum<=u&&i<=n) sum+=c[i++]; //算出吃几堆才能大于上次的
a+=sum;
u=sum;
if(i>n) break; //判断糖是否全被a吃完了,是则停止
cnt++;
sum=c[n--]; //因为是从右往左枚举,所以可以通过n--来操作
while(sum<=u&&i<=n) sum+=c[n--];
b+=sum;
u=sum;
}
printf("%d %d %d\n",cnt,a,b); //最后输出即可
}
return 0;
}
P - Max Sum
最大子区间和:
早就研究过这个问题,也做过类似的题,第一次做的题是单单求最大子区间的和,但是没有问他的下标,我做完的时候给他加了这个功能,但是没有去评测,谁知道竟然是错的!!!
不过看了问了同学储存下标的思路,立马就懂了:
思路如下:
定义一个 当前的最大值,还有一个 最大的最大值,如果 当前的最大值 *大于 *最大的最大值,
更新 最大的最大值 ,还有一个技巧,就是,如果当前的最大值是负数的话,它这个负值对结果就造成了影响,所以令thissum=0,再从下一个元素加起;
代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<set>
#define ios ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int n;
int a[maxn];
int main()
{
ios;
int t,Case=1;
cin>>t;
while(t--){
cin>>n;
int s=1,e=1,te=1;
int thissum=0,maxsum=-maxn;
for(int i=1;i<=n;i++){
cin>>a[i];
thissum+=a[i];
if(thissum > maxsum){
s=te;
e=i;
maxsum=thissum;
}
if(thissum<0){
thissum=0;
te= i+1;
}
}
cout<<"Case "<<Case++<<":"<<"\n";
cout<<maxsum<<" "<<s<<" "<<e<<"\n";
if(t>=1) cout<<"\n";
}
return 0;
}
京公网安备 11010502036488号