陪猪训练1。。。

一周15题。。。基本都是大水题,练练手速和YY思维的那种- -。。

第一周。。。

A:求N个数中出现次数最多的数:用一个数组记录数字出现的次数,因为数只有1K,所以统计完后,暴力去找最大的那个数是什么鬼,然后再暴力跑一遍,看看出现次数最多的那个数是不是唯一的就好了- -。

B:求N个数中唯一不相同的那个数 :sort 看最后两个数是否相同,相同输出第一个数,不同输出最后一个数,毕竟只有一个数不同嘛- -。

C:一个炉石一回合的模拟:会玩炉石的都会做。。。直接模拟一回合后当前的怪是否GG就好了。。。

D:- -统计N个数中超过6000的个数:233333333

前四道是浙江省省赛的一眼题。。。

E:给你N个数,求删掉其中一个数后,相邻两个数差的绝对值最小是多少:数不多,一个个删,一个个判,更新就好了。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int a[105];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int res=999999;
    for(int i=2;i<=n-1;i++)
    {
        int tmp=0;
        for(int j=1;j<=i-2;j++)
        {
            tmp=max(tmp,a[j+1]-a[j]);
        }
        for(int j=i+1;j<n;j++)
        {
            tmp=max(tmp,a[j+1]-a[j]);
        }
        tmp=max(tmp,a[i+1]-a[i-1]);
        res=min(res,tmp);

    }
    cout<<res<<endl;
    return 0;

}

F:给你N位数,有两种操作,操作1是每位加1,操作2是循环右移1位,求最后可以得到的数最小是多少:简单贪心,每位先变成0,变0后在让0到循环至第一位,更新最小值即可,string写起来很方便,第i位循环右移一位变成了(i+j)%n

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

string s,ans;

int  n;

int main()
{
    cin>>n;
    cin>>s;
    ans=s;
    for(int i=0;i<n;i++)
    {
        string temp;
        int t=s[i]-'0';
        for(int j=0;j<n;j++)
        {
            int p=(i+j)%n;
            int k=(s[p]-'0'-t+10)%10;
            temp.push_back(k+'0');
        }
        if(temp<ans)
            ans=temp;
           // cout<<ans<<endl;
    }
    cout<<ans<<endl;
    return 0;
}

G:给你n行m列,问至少删除多少列,可以使得当前的串,满足行列字典序非递减:暴力枚举每一列的相邻两行的元素看字典序是否非递减,不是就删了标记之,否则标记当前列的两行合法,继续往下找下去。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

char s[105][105];
bool ok[105];
bool yes[105];
int n,m;

int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>s[i];
    }
    int res=0;
    bool flag;
    for(int i=0;i<m;i++)
    {
        flag=1;
        memset(ok,0,sizeof(ok));
        for(int j=0;j<n-1&&flag;j++)
        {
            if(yes[j])
            {
                continue;
            }
            if(s[j][i]>s[j+1][i])
            {
                flag=0;
                res++;
                break;
            }
            else if(s[j][i]<s[j+1][i])
            {
                ok[j]=1;
            }
        }
        if(flag)
        {
            for(int j=0;j<n;j++)
            {
                if(ok[j])
                {
                    yes[j]=1;
                }
            }
        }
    }
    cout<<res<<endl;
    return 0;

}

H:一个人可以条过一场电影的T分钟看第i+t分钟的电影,现在给了此人不得不看的n个区间,和一次跳跃的时间,问这个人看我不得不看的n个区间,至少要看多少分钟:如果当前时间+t<看的区间的电影,就一个劲的+t好了(不能超过某场电影的左区间),然后到了一场必须看的电影的时候,记录花的时间,并更新下一个时间的起点为当前电影结束时间+1即可。

I:给你N对字符串(每个字符串只会在N对中出现一次),然后给你m个查询,输出当前字符串对应的位置中两个字符串长度最短的,长度一样,输出字典序最小的:一个map<string,int>直接搞定,没对字符串对应的是当前位置i,然后记录一下i位置查询到后该输出哪个,输出就好。。。。

J:给你两个点,然后给你一个一次函数的abc三个系数,问这两个点是否位于这条直线的两侧:两个点带入直线方程,判断是否异号即可。。。

K:问两个人做一场CF,谁得分更高,直接套题目给的公式。。。

L:给你m对字符串,如果第i对字符串的第二个字符串和第j对字符串的第一个字符串相同,两者就合并:我的做法是开两个字符串数组记录当前存了哪些字符串,然后再输入第j对字符串后,从已有的字符串数组里面进行暴力匹配,如果发现匹配到了,更新就好了,聪明的猪猪同学用了并查集的思想来做,先把没对字符串合并,然后M对输进来之后,找只出现过一次的字符串(假设叫K串吧),并统计,然后再一重循环找只出现过一次的,然后看该字符串的根是否是是K串,如果是,输出K串和找到的这个字符串即可。的确也是个很好的想法,不过猪的代码一开始各种莫名其妙的BUG,帮她DEBUG了一个小时才把BUG全部弄完。。。

我的代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;

int q;
string o[1005];
string n[1005];

int main()
{
    cin>>q;
    int cnt=0;
   while(q--)
   {
       bool flag=0;
       string s1,s2;
       cin>>s1>>s2;
       for(int i=0;i<cnt;i++)
       {
           if(n[i]==s1)
           {
               n[i]=s2;
               flag=1;
               break;
           }
       }
       if(flag==0)
       {
           o[cnt]=s1;
           n[cnt]=s2;
           cnt++;
       }

   }
   cout<<cnt<<endl;
       for(int i=0;i<cnt;i++)
       {
           cout<<o[i]<<" "<<n[i]<<endl;
       }

   return 0;

}
猪的代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
using namespace std;

int vis[5005],re[5005];
int scnt;

map<string,int> w;
int makset(string x)
{
    if(w.count(x)==0)
    {
        w[x]=scnt;
        scnt++;
    }
    return w[x];
}

struct word
{
    char a[250],b[250];
    int x,y;
}s[1005];

int _find(int x)
{
    if(re[x]==x) return x;
    else return re[x]=_find(re[x]);
}

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        w.clear();
        int cnt=0;
        scnt=0;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<3000;i++)
            re[i]=i;
        for(int i=0;i<n;i++)
        {
            scanf("%s%s",s[i].a,s[i].b);
            s[i].x=makset(s[i].a);
            s[i].y=makset(s[i].b);
            vis[s[i].x]++;
            vis[s[i].y]++;
            int p=_find(s[i].x);
            int q=_find(s[i].y);
            if(p!=q) re[q]=p;
        }
        for(int i=0;i<n;i++)
        {
            if(vis[s[i].x]==1) cnt++;
        }
        printf("%d\n",cnt);
        for(int i=0;i<n;i++)
        {
            if(vis[s[i].x]==1)
            {
                for(int j=0;j<n;j++)
                {
                    if(vis[s[j].y]==1&&re[s[j].y]==s[i].x)
                    {
                        printf("%s %s\n",s[i].a,s[j].b);
                        break;
                    }
                }
            }
        }
    }
    return 0;
}

M:思维题,给你N个节点,编号0-N-1,然后给定每个节点的度和与该节点直接相邻的点编号的异或值,让你还原所有边,并告诉你这N个节点和边一定是树或者森林。

思路:用队列模拟,因为是树或者森林,所以肯定存在度为1的点,把度为1的节点全部放入队列,分别让度为1的点出队列,设为f,然后它所对应的异或的值,就是与它有边相连的节点t(毕竟度为1),然后更新t的度,再更新t所对应的节点的异或值,更新就是当前的异或值和f异或一次就OK啦,别问我为什么,那个异或的公式很显而易见啊- -。。。如果t的度也为1,就再次入队,不过要注意模拟的过程会出现度为0的情况,continue就好,否则会有自环产生,然后直到队列空了,就输出就好了。。思路清晰就很好写啦,一道不错的思维题呢- -。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;

struct edge{

int from;
int to;

}a[1<<17];

int d[1<<17],xsum[1<<17];

int n;

queue<int> q;

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>d[i]>>xsum[i];
        if(d[i]==1)
        {
            q.push(i);
        }
    }
    int cnt=0;
    while(!q.empty())
    {
        int f=q.front();
        q.pop();
        if(d[f]==0) continue;
        int t=xsum[f];
        a[cnt].from=f;
        a[cnt].to=t;
        cnt++;
        d[t]--;
        if(d[t]==1)

            q.push(t);
            xsum[t]^=f;

    }
    cout<<cnt<<endl;
    for(int i=0;i<cnt;i++)
    {
        cout<<a[i].from<<" "<<a[i].to<<endl;
    }
    return 0;
}

N:输入输出练习,没啥说的23333333,注意一下奇偶就好。

O:判断是否有节点数大于等于4的环,定好一个起点dfs搜过去就好了,但是尼玛我定义的dx dy不同,答案就会有bug,现在都不知道是为啥,还有我dfs写起来真是要命QAQ。。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
char s[105][105];
bool vis[105][105];

int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
bool flag=0;
void dfs(int x,int y,int xx,int yy)
{
    for(int i=0;i<4;i++)
    {
        if(flag==1)
        {
            return ;
        }
        int _x=x+dx[i];
        int _y=y+dy[i];
        if(s[x][y]==s[_x][_y]&&_x>=0&&_x<n&&_y>=0&&_y<m&&vis[_x][_y]==1&&xx!=_x&&yy!=_y)
        {
            //cout<<_x<<" "<<_y<<endl;
            cout<<"Yes"<<endl;
            flag=1;
            return ;
        }
        if(vis[_x][_y]==0)
        {
            if(s[x][y]==s[_x][_y]&&_x>=0&&_x<n&&_y>=0&&_y<m)
            {
                //cout<<_x<<" "<<_y<<endl;
                vis[_x][_y]=1;
                dfs(_x,_y,x,y);
            }
        }
    }
}

int main()
{
    cin>>n>>m;
    flag=0;
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++)
    {
        cin>>s[i];
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(vis[i][j]==0&&flag==0)
            {
                dfs(i,j,i,j);
            }
        }
    }
    if(flag==0)
    {
        cout<<"No"<<endl;
    }
    return 0;
}

- -好好带一个小朋友,争取带出来,自己快要滚粗了,总得留下点什么给后人QAQ。。。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值