2023上海理工大学校内选拔赛A-D题

前言

不要在意标题,既然是随记,就随性点()

 

今天参加了2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)这个比赛,只做出来两道,赛后又补了两道,其余的也看了看大佬的代码有些能看懂,有些看不懂,也瞻仰了大佬的代码(看到最后一题有位清华大佬写了300多行代码orz)

 

不过这次比赛也是有点收获的,先把自己的四道题解写下来吧(或许也不能说是题解,只是做题时的思路)

 

A Xor B Problem

题目说了一堆,最后理解下来其实就是一个数组for循环两遍找a[i] 与a[j](i!=j)是否相同,相同的话就ans++;

不过当我看了这个数据范围后就放弃了双for

 

 

 emm,我觉得应该会超时(没有双for去算),于是我去观察了一下,其实也可以用两个单独的for循环,用一个数组单独记录每个输入的数字的出现次数,然后再平方就可以了.

(值得注意的是,这个数据并不是1e5,而是要大于1e5,至少1e6,当时比赛中有通报过,否则是过不了ac的)

 

代码实现:

#include<bits/stdc++.h>
#define int long long
using  namespace std;

const int  N = 1e6+10;
int  n,m,a[N],b[N],suma,sumb,ans;
signed main()
{
    scanf("%lld",&n);
    for(int i=0;i<n;i++)
    {
      scanf("%lld",&m);
      a[m] ++;        
    }
    for(int i=0;i<N;i++)
     ans += pow(a[i], 2);
     printf("%lld",ans);
    return 0;
}

 

 

吃苹果

 

题意就是小龙的n个苹果在早上吃还是晚上吃获得的愉悦值和最大,不过在晚上只能吃k天,于是我们只要算出晚上与白天愉悦值差(即白天减去晚上的愉悦值)最小的进行排序,然后取k天晚上的,再从k+1天取白天的就可以了.

 

代码实现:

#include<bits/stdc++.h>
#define int long long
using  namespace std;

const int  N = 1e5+10;
int  n,m,a[N],b[N],suma,sumb,ans;
struct ss{
 int x,y;
}s[N];
bool cmpb(struct ss l,struct ss r)
{
    return l.x - l.y < r.x - r.y;
}
signed main()
{
    scanf("%Ld %Ld",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%Ld %Ld",&s[i].x,&s[i].y);      
    }
    sort(s,s+n,cmpb);
    for(int i=0;i<m;i++)
        ans += s[i].y;
    for(int i=m;i<n;i++)
        ans += s[i].x;
    printf("%Ld\n",ans);
    return 0;
}

 

 

n皇后问题

这道题也是好理解的,就是把皇后的路线(同行,同列,同斜)进行标记,之后输入的再进行判断即可.

 

说来惭愧,其实在我印象里我好像做过这种题,不过我当时想的是用二维数组的,(但是这个数据范围1e6肯定是不能用二维的a----), 于是我就没过.

 

后来看了一下别人的代码突然理解了,这里有个小技巧,那就是坐标轴上对角线的差和是不变的,于是我们可以拿这个来做标记,凡是和皇后对角线差和相同的就不能放皇后,还有就是如果对角线差事负数的话,可以加一个n或者是一个很大的数来使它变得合理.

 

 

代码实现:

#include<bits/stdc++.h>
#define int long long
using  namespace std;
const int  N = 1e7+10;
int  n,m,a[N],t,x,y,b[N],c[N],d[N];
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin >> n >> t;
    while(t--)
    {
            cin >> x >> y;
            if(!a[x] && !b[y] && !c[x+y] && !d[x-y+n])
            {    
              a[x] = b[y] = c[x+y] = d[x-y+n] = 1;            
            cout << "Yes\n"; 
              }
            else
            {
              cout << "No\n";                
            }

    }
    return 0;
}

 

 

分苹果

明明是第四题,但却是我一次就过的题...

 

简单说下题意吧,就是用两根棍子交叉,然后记录在这两根棍子的四个区域的苹果数量从小到大输出就行了.

可以想象成坐标轴,然后统计四个象限的苹果数量(就是把苹果坐标带进两条线的方程判断大于0和小于0)从小到大输出.

 

代码实现:

#include<bits/stdc++.h>
#define int long long
using  namespace std;

const int  N = 1e5+10;
int  n,m,a[N],ae,be,ce,ar,br,cr,x,y;
int frist(int c,int b)
{
    return c * ae + b * be + ce;
}
int second(int c,int b)
{
    return c * ar + b * br + cr;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin >> n;
    cin >> ae >> be >> ce ;
    cin >> ar >> br >> cr ;
    while(n--)
    {
        cin >> x >> y;
        if(frist(x,y)>0 && second(x,y)>0)
         a[1] ++ ;
        if(frist(x,y)>0 && second(x,y)<0)
         a[2] ++ ;
        if(frist(x,y)<0 && second(x,y)>0)
         a[3] ++;
        if(frist(x,y)<0 && second(x,y)<0)
         a[4] ++ ; 
    }
    sort(a+1,a+5);
    for(int i=1;i<5;i++)
      cout << a[i] << ' ';
    return 0;
}

 

后语

没了,其他的题有些能看懂但对于蒟蒻的我还不能完全理解,就写道这儿吧.

噢,还有,今天从学长那学到个小知识:

           在使用

ios::sync_with_stdio(0);

这个优化cin的效率时不要和scanf会混用.切记!!!

 

否则可能会导致输入的数据错误和效率变慢;

具体的也不太懂,可以参考下面两篇文章:

cin输入的优化与cin和scanf混用时输入错误的问题 - 代码先锋网 (codeleading.com)

竞赛中应该用scanf还是cin? scanf&printf与cin&cout的比较+快读快写_为什么推荐用scanf不用cin_小白还在写代码的博客-CSDN博客

 

posted @ 2023-03-12 01:22  Ke_scholar  阅读(67)  评论(0编辑  收藏  举报