@[TOC]
比赛试题

A 最短路

B 组队

题解:
先排序,然后二分查找比当前数a[i]大k的第一个数坐标是多少,假设坐标是j,那么j之后的都要比i大k,只有j之前,i之后的符合题意,i与j有j-i个数,求最大值

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+4;
ll a[maxn];
int main()
{
    int t;
    cin>>t;
    ll n,k;
    while(t--)
    {
        cin>>n>>k;
        for(int i=1;i<=n;i++)cin>>a[i];
        sort(a+1,a+1+n);
        int sum=0;
        int ans=-1;
        for(int i=1;i<=n;i++)
        {
            sum=upper_bound(a+1,a+n+1,a[i]+k)-a;
            ans=max(ans,sum-i);
        }
        cout<<ans<<endl;
    }
    return 0;
} 

C 十面埋伏

我一开始想直接在#周围标记,然后输出就行,
发现会存在#围成密闭空间,那么空间里就不用围起来
我又发现围起来的部分都是最左边#的左边,最上边#的上边,最右边#的右边,最下边#的下边,样例1能过,但数据过不了一半,因为如果有深沟处理不了,如样例2
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
char a[505][505];
int maxx[505],minn[505];
int main()
{
    int n,m;

    cin>>n>>m;
        char ch=getchar();
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
        ch=getchar();
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]=='#')
            {
                a[i][j-1]='*';
                break;
            }
        }
    } 

        for(int i=1;i<=n;i++)
    {
        for(int j=m;j>=1;j--)
        {
            if(a[i][j]=='#')
            {
                a[i][j+1]='*';
                break;
            }
        }
    } 


        for(int j=1;j<=m;j++)
    {
        for(int i=1;i<=n;i++)
        {
            if(a[i][j]=='#')
            {
                a[i-1][j]='*';
                break;
            }
        }
    }

             for(int j=1;j<=m;j++)
    {
        for(int i=n;i>=1;i--)
        {
            if(a[i][j]=='#')
            {
                a[i+1][j]='*';
                break;
            }
        }
    }







         for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cout<<a[i][j];
        }
        cout<<endl;
    }
}

最后我才意识到,要把#周围全处理,其实直接dfs'.'
就是把圈外的'.'格dfs,然后标记,‘#’旁边被标记过的'.'格子就可以改成‘*’

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 505;

int n,m;

int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
 char a[maxn][maxn];
bool vis[maxn][maxn];


void dfs(int x,int y){
    vis[x][y]=true;
    for(int i=0;i<4;i++){
        int tx=x+dx[i];
        int ty=y+dy[i];
        if(vis[tx][ty]||tx<1||tx>n||ty<1||ty>m||a[tx][ty]!='.') continue;
        dfs(tx,ty);
    }
}
int main(){

    cin>>n>>m;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++){
        cin>>a[i][j];
    }
    dfs(1,1);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]=='#')
            {
                for(int k=0;k<4;k++)
                {
                    int tx=i+dx[k];
                    int ty=j+dy[k];
                   if(vis[tx][ty]) a[tx][ty]='*';
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
            for(int j=1;j<=m;j++) 
        {
            cout<<a[i][j];
        }
        cout<<endl;
    }

    return 0;
}

D 牛妹吃豆子

E 旅旅旅游

F 斗兽棋

大大大模拟。。
直接if比较就可以,因为这四个首字母不一样,直接首字母比较就可以。对了如果出的两个动物没有关系,也算平局
最后记住:舔狗一无所有!!!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+4;
string s1="tiangou txdy";
string s2="tiangou yiwusuoyou";
int main()
{
    string w1,w2;
    cin>>w1>>w2;
    if(w1[0]=='e'&&w2[0]=='t')cout<<s2;
    else if(w1[0]=='t'&&w2[0]=='c')cout<<s2;
    else if(w1[0]=='c'&&w2[0]=='m')cout<<s2;
    else if(w1[0]=='m'&&w2[0]=='e')cout<<s2;

    else if(w2[0]=='e'&&w1[0]=='t')cout<<s1;
    else if(w2[0]=='t'&&w1[0]=='c')cout<<s1;
    else if(w2[0]=='c'&&w1[0]=='m')cout<<s1;
    else if(w2[0]=='m'&&w1[0]=='e')cout<<s1;

    else if(w1[0]=='e'&&w2[0]=='e')cout<<s2;
    else if(w1[0]=='t'&&w2[0]=='t')cout<<s2;
    else if(w1[0]=='c'&&w2[0]=='c')cout<<s2;
    else if(w1[0]=='m'&&w2[0]=='m')cout<<s2;
    else cout<<s2;

    return 0;
} 

G 做题

我一开还以为会存在性价比比较什么的,后来发现想多了。。
排个序从小开始算就完事了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+4;
int a[maxn];
int main()
{
    long long n,m;
    scanf("%lld%lld",&n,&m);

    for(int i=1;i<=n;i++)
    scanf("%lld",&a[i]);

    sort(a+1,a+1+n);
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(m-a[i]>=0)sum++;
        else break;
        m-=a[i];
    }
    printf("%lld",sum);
    return 0;
} 

H 人人都是好朋友

第一眼过去并查集,将有关的人联系在一起,判断时直接查询是否为父亲节点是否相同
注意a和b的范围远大于n,说明小弟不可能都登场,我们只需要小弟们的相对大小,即能区分开就行,所以离散化处理

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e6 + 3;
int father[maxn];
int T;
int a[maxn];
int b[maxn];
int c[maxn];
int d[maxn];
int n;
bool f;
int find(int x)
{
    if(father[x]!=x)return father[x]=find(father[x]);
    else  father[x];
}
void lisanhua(int tot)
{
        sort(d + 1, d + tot + 1);
        tot = unique(d + 1, d + tot + 1) - d;
        for (int i = 1; i <= n; i++)
        {
            a[i] = lower_bound(d + 1, d + tot + 1, a[i]) - d;
            b[i] = lower_bound(d + 1, d + tot + 1, b[i]) - d;
        }
}
void init(int tot)
{
            for (int i = 1; i <= tot; i++)father[i] = i;
} 
void unionn(int i)
{
    father[find(a[i])]=find(b[i]);
}
bool iff(int i)
{
    if(find(a[i])==find(b[i]))return 1;
    else return 0;
}
int main()
{

    scanf("%d",&T);
    while (T--)
    {

        cin >> n;
         f = 1;
        int tot = 0;
        for (int i = 1; i <= n; i++)
        {
            scanf("%d%d%d",&a[i],&b[i],&c[i]);
            d[++tot] = a[i];
            d[++tot] = b[i];
        }
        lisanhua(tot);//离散化 
        init(tot);//初始化 
        for (int i = 1; i <= n; i++)
        {
            if (c[i])unionn(i);

        }
        for (int i = 1; i <= n; i++)
        {
            if (!c[i])
               if(iff(i))f = 0;
        }
        if (f)
            cout<<"YES";
        else
            cout<<"NO";
    }
    return 0;
}

I 求和

DFS序加线段树(或者树状数组)维护
代码略

J 建设道路

直接做n^2^肯定超时,需要优化,我们可以将公式一步步转化,最后转成O(n)
在这里插入图片描述
pre[]为a[i]的前缀和
pre1[]为a[i]^2^的前缀和
O(n)就可以算出

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=5e5+4;
ll a[maxn];
ll pre[maxn]; 
ll pre1[maxn];
ll sum;
ll ans1,ans2,ans3,ans;
int main()
{
    int n;
    scanf("%d",&n);

    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        pre[i]=(pre[i-1]+a[i])%mod;
        pre1[i]=(pre1[i-1]+a[i]*a[i])%mod;
    }
    for(int i=1;i<=n;i++)
    {
        ans1 = ((n - i) * ((a[i] * a[i]) % mod)) % mod;
        ans2 = ((2 * a[i]) % mod) * ((pre[n] - pre[i] + mod) % mod) % mod;
        ans3 = (pre1[n] - pre1[i]+mod) % mod;
        ans = (ans1 - ans2 + ans3+mod) % mod;
        sum=(sum+ans)%mod;
    }
    printf("%lld",sum);


    return 0;
} 

还有其他推法解法,但是我没看懂。。。我太弱了