第一次训练赛题解

A 简单的签到题

 知识点:归并排序

思路:当我们排序时,对于左区间[left,mid]和右区间[mid+1,right],因为各自区间内部都是上升的,所以如果s[left]>s[mid+1],也就意味着比s[mid+1]大的数一共有mid-left+1个,然后再看s[mi+2],依次比较。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+5;
int s[N],ans[N];
ll cnt=0;int n=0;
void merge_sort(int left,int right)
{
	int mid=left+right>>1;
	int i=left,j=mid+1,k=left;
	while(i<=mid&&j<=right){
		if(s[i]<=s[j]){
			ans[k++]=s[i++];
		}else{
			ans[k++]=s[j++];
			cnt+=(mid-i+1);
		}
	}
	while(i<=mid){
		ans[k++]=s[i++];
	}
	while(j<=right){
		ans[k++]=s[j++];
	}
	for(k=left;k<=right;k++){
		s[k]=ans[k];
	}
}
void merge(int left,int right)
{
	int mid=(left+right>>1);
	if(left==right){
		ans[left]=ans[right];
	}else {
		merge(left,mid);
		merge(mid+1,right);
		merge_sort(left,right);
	}
}
int main()
{
	scanf("%d",&n);
	int i,j;
	for(i=1;i<=n;i++) scanf("%d",&s[i]);
	merge(1,n);
	printf("%lld\n",cnt);
} 

E全世界的水水泥工联合起来

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
char s[N][N];
int vict[N][N];
struct node{
	int x,y;
};
queue<node>q;
int dx[8]={-1,0,1,1, 1, 0,-1,-1};
int dy[8]={ 1,1,1,0,-1,-1,-1, 0};
int main()
{
	int n,m;scanf("%d%d",&n,&m);
	int i,j;
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			cin>>s[i][j];
		}
	}
	int cnt=0;
	if(s[1][1]=='1') cnt=0;
	else cnt=1;
	node cc1;
	cc1.x=1,cc1.y=1;
	q.push(cc1);
	s[1][1]='3';
	while(!q.empty()){
		for(i=0;i<8;i++){
			int tx=q.front().x+dx[i];
			int ty=q.front().y+dy[i];
			if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&s[tx][ty]=='0'){
				s[tx][ty]='3';
				cnt++;
				node temp;
				temp.x=tx,temp.y=ty;
				q.push(temp);
			}
		}
		q.pop();
	}
	
	cout<<cnt<<endl;
}

H 简简单单种个树

 考察思维的一道题,从数据中看,种了n次,数据范围是0~1e8,用数组储存来表示每个地方是否种树肯定会内存超限,所以不妨参考会议安排题目的方法进行排序,然后进行加减;

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
struct node{
	int start,end;
}s[N];
bool cmp(node a,node b)
{
	return a.end<=b.end;
}
int main()
{
	int n;scanf("%d",&n);
	int i,j;
	for(i=1;i<=n;i++){
		scanf("%d%d",&s[i].start,&s[i].end);
	}
	sort(s+1,s+1+n,cmp);
	ll cnt=s[n].end-s[n].start+1;
	int cha=s[n].start;
	for(i=n-1;i>=1;i--){
		if(s[i].start>=cha){
			continue;
		}
		else {
			if(s[i].end>=cha){
				cnt+=cha-s[i].start;
			}else{
				cnt+=s[i].end-s[i].start+1;
			}
			cha=s[i].start;
		}
	}
	printf("%lld\n",cnt*2);
}

 

K 真真签到题

考点:dp递归

思考:本题不能采用搜索,数据范围达到了500,若用深度优先搜索会超时,而广度优先搜索会导致内存超限,最好的做法是使用dp递归。

         

#include<bits/stdc++.h>
using namespace std;
const int N=505;
int s[N][N],maxt[N][N];
int main()
{
	int n;scanf("%d",&n);
	int i,j;
	for(i=1;i<=n;i++){
		for(j=1;j<=i;j++){
			scanf("%d",&s[i][j]);
		}
	}
	maxt[1][1]=s[1][1];
	for(i=2;i<=n;i++){
		for(j=1;j<=i;j++){
			/*对于最两边的值需注意,不可用为赋值的地方去加*/ 
			if(j==1){
				maxt[i][j]=s[i][j]+maxt[i-1][j];
			}
			else if(j==i){
				maxt[i][j]=s[i][j]+maxt[i-1][j-1];
			} 
			else{
				maxt[i][j]=max(s[i][j]+maxt[i-1][j],s[i][j]+maxt[i-1][j-1]);
			}	
		}
	}
	int maxans=-1e5;
	for(j=1;j<=n;j++){
		maxans=max(maxans,maxt[n][j]);
	}
	printf("%d\n",maxans);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值