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);
}