A Little Contest

(https://ac.nowcoder.com/acm/contest/3002/G)
我的思想:1,给出两个标记点first,last然后依次移动并将移动到位置的字母总数减一并维护ans。但是感觉不太好写就扔掉了。
2.暴力查找,结果超时了而且我太菜了想不出新方法了(困。。。)
结果一直交一直t,然后就放弃了。
代码如下:

#include <bits/stdc++.h>

using namespace std;
const int MAX = 99999999;
char s[200010];
int main()
{
    int n,m;
    int sum;
    int ans = MAX;
    scanf("%d%d",&n,&m);
    scanf("%s",s);
    for(int i = 0;i < n;++i){
        sum = 0;
        for(int j = i;j < n;++j){
            if(s[i] == s[j]){
                sum++;
            }
            if(sum == m){
                ans = min(ans,j - i + 1);
                break;
            }
        }
    }
    printf("%d\n",ans == MAX ? -1 : ans);
}

感觉还是挺好的吧至少我造的样例过了。就是接近n^2的复杂度跑不了那么大的范围。
赛后看到几位大佬的(果然还是赛后共享代码更好)
摘录几位:
其一,用队列,代码如下:
参考id: xch233

#include <bits/stdc++.h>

using namespace std;
const int MAX = 0x3f3f3f3f;
string s;
int main()
{
    int n,k;
    int ans = MAX;
    scanf("%d%d",&n,&k);
    cin >> s;
    for(int i = 0;i < 26;++i){
        int cnt = 0;
        queue<int> q;
        for(int j = 0;j < n;++j){
            if(s[j] - 'a'== i){
                q.push(j);
                cnt++;
                if(cnt == k){
                    int tem = q.front();
                    q.pop();
                    cnt--;
                    ans = min(ans,j - tem + 1);
               }
            }
        }
    }
    printf("%d\n",ans == MAX ? -1 : ans);
}

队列的性质很好的解决了我想的first和last标记的问题,不过我就是想不到啊。
其二,这个过于强大,瞻仰一下,比赛开始四分钟就做出来,真正的强者代码如下:
参考 id:wrjlinkkkkkk

#include <bits/stdc++.h>

using namespace std;
const int MAX = 0x3f3f3f3f;
const int maxn = 2e5+100;
int num[55];
int d[55][maxn];
char s[maxn];
int main()
{
    int n,k;
    int ans = MAX;
    scanf("%d%d",&n,&k);
    scanf("%s",s + 1);///可以将字符串首位从一开始
    n = strlen(s + 1);
    for(int i = 1;i <= n;++i){
        int now = s[i] - 'a';
        d[now][++num[now]] = i;///now记录字符,num记录字符数量整个d数组记录某字符出现的位置
    }
    for(int i = 0;i < 24;++i){
        for(int j = 1;j + k - 1 <= num[i];++j){
            ans = min(ans,d[i][j + k - 1] - d[i][j] + 1);///如果某字符出现次数超过或等于k
        }
    }
    printf("%d\n",ans == MAX ? -1 : ans);
}


(https://ac.nowcoder.com/acm/contest/3002/A)
这个题吧,讲真我一直没搞懂我错在何处,规律我找的到是挺快的,样例也过了就是一直WA,搞得我心烦意乱。
错误代码:

#include <bits/stdc++.h>

using namespace std;
const int MAX = 1000000007;
int main()
{
    long long n,m;
    long long n1,m1;
    scanf("%lld%lld",&n,&m);
    long long ans = (2 * n * (n - 2) * (m - 1) % MAX+ 2 * m * (m - 2) * (n - 1) % MAX) % MAX;
    if(n > 4) n1 = 2 * (n - 4) + 4;
    else {
        if(n == 2) n1 = 0;
        if(n == 3) n1 = 2;
        if(n == 4) n1 = 4;
    }
    if(m > 4) m1 = 2 * (m - 4) + 4;
    else {
        if(m == 2) m1 = 0;
        if(m == 3) m1 = 2;
        if(m == 4) m1 = 4;
    }
    ans += ((n - 1) * (n - 2) * m1  % MAX + (m - 1) * (m - 2) * n1 % MAX) % MAX;
    ans = ans % MAX;
    printf("%lld\n",ans);
}

我的大致想法和题解差不多,就是将面积为一的三角形分成两种情况:1.长是一的边和x或y轴平行。2.长是二的边和x或y轴平行。两种情况加起来就是总数。比赛时我看这个题交的人很多但正确率不甚高,估计好多像我一样样例过了但永远A不了的人。
正确代码:

#include <bits/stdc++.h>

using namespace std;
const int MAX = 1000000007;
int main()
{
    long long n,m;
    long long n1,m1;
    long long ans;
    scanf("%lld%lld",&n,&m);
    n1 = (((m - 2) * (n - 1)) % MAX * (m + n - 2)) % MAX * 2;
    m1 = (((n - 2) * (m - 1)) % MAX * (m + n - 2)) % MAX * 2;
    ans = ((n1 % MAX) + (m1 % MAX)) % MAX;
    printf("%lld\n",ans);
}

我在两个程序上都跑了一下极限情况即m = n = 1e9 - 1,我的程序结果是164378202,
正确答案是111999785,但是经过测验在100以内我的程序和正确答案结果是一致的
只能说明我的规律在较大数并不适用。还是我太菜了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值