2019 - 假期第二场(2019.1.25)

1、 Almost Sorted Array
We are all familiar with sorting algorithms: quick sort, merge sort, heap sort, insertion sort, selection
sort, bubble sort, etc. But sometimes it is an overkill to use these algorithms for an almost sorted array.
We say an array is sorted if its elements are in non-decreasing order or non-increasing order. We
say an array is almost sorted if we can remove exactly one element from it, and the remaining array is
sorted. Now you are given an array a1, a2, …, an, is it almost sorted?
Input
The first line contains an integer T indicating the total number of test cases. Each test case starts with
an integer n in one line, then one line with n integers a1, a2, …, an.
• 1 ≤ T ≤ 2000
• 2 ≤ n ≤ 105
• 1 ≤ ai ≤ 105
• There are at most 20 test cases with n > 1000.
Output
For each test case, please output ‘YES’ if it is almost sorted. Otherwise, output ‘NO’ (both without
quotes).
Sample Input
3
3
2 1 7
3
3 2 1
5
3 1 4 1 5
Sample Output
YES
YES
NO

题意:给定一个序列,判断移走数字之后是否是有序的(非递增或者非递减都可以,也有可能元素全相同)

思路1:
判断非递增、非递减两种情况
当移走一个元素时,就会形成一个新的顺序,需要判断前后两个元素的大小,判断是否有序

思路2:
正逆序 LIS
Code:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
typedef long long LL;
using namespace std;

bool cmp(int a,int b)
{
    return a>b;
}

int a[100005],b[100005],c[100005];
int aa[100005],bb[100005];

int main()
{
    int t,n,flag,sum,sum1,flagg;
    scanf("%d",&t);
    while(t--)
    {

        memset(aa,0,sizeof(aa));
        memset(bb,0,sizeof(bb));
        flag=0,flagg=0;
        sum=0,sum1=0;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
            c[i]=a[i];
        }

        sort(b,b+n);
        sort(c,c+n,cmp);

        for(int i=0; i<n; i++)
        {
            if(a[i]==b[i])
                sum++;
            if(a[i]==c[i])
                sum1++;
        }

        if(sum==n||sum1==n)
        {
            printf("YES\n");
            continue;
        }

        sum=0,sum1=0;

		// 判断非递增顺序
        for(int i=1; i<n; i++)
        {
        	// 不满足递减的条件
           if(a[i]>a[i-1])
            {

                if(sum>=1)
                {
                    flag=1;
                    break;
                }

                sum++;
                if(i==1) // 对于第 i 个元素,如果其右满足递减,则可以移走该元素
                {
                    if(a[i]>=a[i+1])
                        continue;
                    else   //  否则不满足题意直接退出
                    {
                        flag=1;
                        break;
                    }
                }
                if(i==n-1)   // 对于第 i 个元素,如果其左满足递减,则可以移走该元素
                {
                    if(a[i-1]<=a[i-2])
                        continue;
                    else
                    {
  				        flag=1;
                        break;
                    }
                }
             	//  对于第 i 个元素,如果去掉该元素
                //  能够使得其左三位是递减的或者右三位递增则可以移走该元素,否则条件不成立退出
                if(a[i]<=a[i-2]||a[i-1]>=a[i+1]) 
                    continue;
                else
                {
                    flag=1;
                    break;
                }
            }
        }
        
        //  判断非递减顺序
        for(int i=1; i<n; i++)
        {
           // 不满足非递减顺序的条件
            if(a[i]<a[i-1])
            {
                if(sum1>=1)
                {
                    flagg=1;
                    break;
                }

                sum1++;

                if(i==1)    // 对于第 i 个元素,如果其右满足递增,可以移走该元素
                {
                    if(a[i]<=a[i+1])
                        continue;
                    else
                    {
                        flagg=1;
                        break;
                    }
                }

                if(i==n-1)  // 对于第 i 个元素,如果其左满足递增,可以移走该元素
                {
                    if(a[i-1]>=a[i-2])
                        continue;
                    else
                    {
                        flagg=1;
                        break;
                    }
                }
				
				//  对于第 i 个元素,如果去掉该元素
                //  能够使得其左三位是递增的或者右三位递增的则可以移走该元素,否则条件不成立退出
                if(a[i+1]>=a[i-1]||a[i]>=a[i-2])
                    continue;
                else
                {
                    flagg=1;
                    break;
                }
            }
        }

        if(flag==0||flagg==0)
            printf("YES\n");
        else
            printf("NO\n");
    }
}

2、House Building
Have you ever played the video game named
Minecraft? This game has been one of the
world’s most popular game in recent years. The
world of Minecraft is made up of lots of 1×1×1
blocks in a 3D map. Blocks are the basic units
of structure in Minecraft, there are many types
of blocks. A block can either be a clay, dirt, water, wood, air, … or even a building material
such as brick or concrete in this game.
Nyanko-san is one of the diehard fans of the
game, what he loves most is to build monumental houses in the world of the game. One day, he
found a flat ground in some place. Yes, a super
flat ground without any roughness, it’s really a
lovely place to build houses on it. Nyanko-san
decided to build on a n × m big flat ground, so he drew a blueprint of his house, and found some
building materials to build.
While everything seems goes smoothly, something wrong happened. Nyanko-san found out he had
forgotten to prepare glass elements, which is a important element to decorate his house. Now Nyankosan gives you his blueprint of house and asking for your help. Your job is quite easy, collecting a
sufficient number of the glass unit for building his house. But first, you have to calculate how many
units of glass should be collected.
There are n rows and m columns on the ground, an intersection of a row and a column is a 1 × 1
square, and a square is a valid place for players to put blocks on. And to simplify this problem, Nynakosan’s blueprint can be represented as an integer array ci,j (1 ≤ i ≤ n, 1 ≤ j ≤ m). Which ci,j indicates
the height of his house on the square of i-th row and j-th column. The number of glass unit that
you need to collect is equal to the surface area of Nyanko-san’s house(exclude the face adjacent to the
ground).

Input
The first line contains an integer T indicating the total number of test cases. First line of each test case
is a line with two integers n, m. The n lines that follow describe the array of Nyanko-san’s blueprint,
the i-th of these lines has m integers ci,1, ci,2, …, ci,m, separated by a single space.
• 1 ≤ T ≤ 50
• 1 ≤ n, m ≤ 50
• 0 ≤ ci,j ≤ 1000
Output
For each test case, please output the number of glass units you need to collect to meet Nyanko-san’s
requirement in one line.

在这里插入图片描述
Sample Input
2
3 3
1 0 0
3 1 2
1 1 0
3 3
1 0 1
0 0 0
1 0 1
Sample Output
30
20

题意:
nm 的矩阵代表 i,j 处的高度,即该位置有几个正方体
然后求该几何体的表面积
为 1
1*1 的,一个正方体的表面积 为 6

思路:
先求出总共的表面积有多少
然后减去 底面积 减去 横竖相邻的边 减去 上下相邻的边
注意:
横竖相邻的边 和 上下相邻的边 都是接触两个正方体,因此减去两个
由于减去了底面积,因此当减去上下相邻的边时,减去 ( 高度 - 1 )*2 个边的表面积

减去横竖相邻的边:
对于 i j ,减去右边(i,j+1) 和下边 (i+1,j)的接触面
由于高度不一样,因此要减去 两者中 最小的高度,即为接触面

CODE:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
typedef long long LL;
using namespace std;

int main()
{
    int t,n,m;
    int a[55][55];
    int sum,sum1,ans;
    scanf("%d",&t);
    while(t--){
        sum=0,sum1=0,ans;
        scanf("%d %d",&n,&m);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                scanf("%d",&a[i][j]);
                if(a[i][j]>0){
                    sum++;
                    sum1+=a[i][j];
                }
            }
        }


        ans=sum1*6-sum;

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(a[i][j]!=0){
                    if(j!=m-1&&a[i][j+1]!=0)
                        ans-=2*(min(a[i][j],a[i][j+1]));
                    if(i!=n-1&&a[i+1][j]!=0)
                        ans-=2*(min(a[i][j],a[i+1][j]));
                }
            }
        }

        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(a[i][j]>1){
                    ans-=(a[i][j]-1)*2;
                }
            }
        }

        printf("%d\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值