Codeforces Round #354 (Div. 2) 大讨论之术+模拟+分层图+bfs

本文回顾了Codeforces Round #354(Div. 2)的比赛,讨论了A、B、C、D四道题目。A题和B题看似简单却易出错,C题需要考虑特殊情况,D题则是复杂的分层图BFS问题。作者反思了自己的错误,如C题的边界情况判断不全导致FST,D题因数组大小不足引发TLE。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

辣鸡CF 毁我青春

ABC三题都很SB,但需要大讨论之术或者代码写起来容易出错
D题一个一眼题,但写起来神烦,最终还卡了我数组大小
E我没看

最后C题惨遭FST,D后来改了改数组大小就过了,E还是没看

总结:不会写代码了

说白了还是人弱……

跪膜没FST并且rank44并且rating涨了二百多的yzy

掉了六十多rating,竟然这么少 不科学


A

题意:给一个排列,要求必须交换一次使得1和n的位置离得最远。

SB题,要特判一下奇怪的东西……代码写的丑

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

typedef long long LL;
const int SZ = 200010;
const int INF = 1000000010;

int read()
{
    int n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a >= '0' && a <= '9') { n = n * 10 + a - '0'; a = getchar(); }
    if(flag) n = -n;
    return n;
}

int num[SZ];

int main()
{
    int n = read();
    int pos1,pos2;
    for(int i = 1;i <= n;i ++)
    {
        num[i] = read();
        if(num[i] == 1) pos1 = i;
        if(num[i] == n) pos2 = i;
    }
    if(n == 1)
    {
        printf("0"); return 0;
    }
    if(n == 2)
    {
        printf("1"); return 0;
    }
    if(((pos1 == 1 && pos2 == n) || (pos1 == n || pos2 == 1)))
    {
        printf("%d",n - 1);
        return 0;
    }
    printf("%d\n",max(max(abs(n - pos1),abs(1 - pos1)),max(abs(n - pos2),abs(1 - pos2))));
    return 0;
}


B

题意:给n行杯子,构成金字塔形,其中第i行i个杯子。每分钟往顶层的杯子灌一个杯子的量的水,问n排杯子在t时刻后有多少个杯子是满的。

n<=10,0<=t<=10000

我竟然画了半天杨辉三角,最后还是写的模拟……这告诉我们不需要去想一些高端的算法只要能过就行了……

还有t=0的情况……

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

typedef long long LL;
const int SZ = 200010;
const int INF = 1000000010;

int read()
{
    int n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a >= '0' && a <= '9') { n = n * 10 + a - '0'; a = getchar(); }
    if(flag) n = -n;
    return n;
}

double bz[233][233],mi[233];

int n,t;

void dfs(int x,int y,double d)
{
    if(x == n + 1) return ;
    if(bz[x][y] == 1)
        dfs(x + 1,y,d / 2),dfs(x + 1,y + 1,d / 2);
    else
        bz[x][y] += d;
    return ;
}

int main()
{
    n = read(),t = read();
    double xxx = 1;
    for(int i = 1;i <= n;i ++)
        mi[i] = xxx,xxx /= 2.0;
    while(t --)
        dfs(1,1,1);
    int ans = 0;
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= i;j ++)
            if(abs(bz[i][j] - 1.0) < 1e-8)
                ans ++;
    printf("%d",ans);
    return 0;
}


C

题意:给一个只含有a和b的字符串,要求最多修改k个字符使得最长连续相同字符长度最长。输出最长长度。

n<=10w,0<=k<=n

把a和b的出现位置单独存起来,每次修改k个字符必定是连续的k个a或者k个b,答案可以由区间左右端点所在位置更新。注意要由n或1更新的情况。

若有少于k个a或者k个b,答案是n

还要判一下k=0的情况。

FST原因:k=0的时候,没有判由1或者n更新的情况。
浪费大量时间原因:vector的.size()是unsigned类型,当vector为空的时候,.size()-1会RE

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

typedef long long LL;
const int SZ = 200010;
const int INF = 1000000010;

int read()
{
    int n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a >= '0' && a <= '9') { n = n * 10 + a - '0'; a = getchar(); }
    if(flag) n = -n;
    return n;
}

vector<int> a,b;

char s[SZ];

int main()
{
    int n = read(),k = read();
    scanf("%s",s + 1);
    for(int i = 1;i <= n;i ++)
        if(s[i] == 'a') a.push_back(i);
        else b.push_back(i);
    if(k == 0)
    {
        int ans = 0;
        for(int i = 0;i < (int)a.size() - 1;i ++)
            ans = max(ans,a[i + 1] - 1 - (a[i] + 1) + 1);
        if(a.size() == 1)
            ans = max(ans,max(a[0] - 1,n - a[0]));
        for(int i = 0;i < (int)b.size() - 1;i ++)
            ans = max(ans,b[i + 1] - 1 - (b[i] + 1) + 1);
        if(b.size() == 1)
            ans = max(ans,max(b[0] - 1,n - b[0]));
        if(a.size() <= k || b.size() <= k)
            ans = n;
        printf("%d\n",ans);
        return 0;
    }
    int ans = 0;
    for(int i = 0;i < (int)a.size();i ++)
    {
        int r = i + k - 1;
        if(r >= a.size()) break;
        if(i == 0)
        {
            if(r + 1 >= 0 && r + 1 < a.size())
                ans = max(ans,a[r + 1] - 1);
        }
        else if(r == (int)a.size() - 1)
        {
            if(i - 1 >= 0)
                ans = max(ans,n - (a[i - 1] + 1) + 1);
        }
        else
        {
            if(r + 1 >= 0 && r + 1 < a.size() && i - 1 >= 0)
                ans = max(ans,(a[r + 1] - 1) - (a[i - 1] + 1) + 1);
        }
    }
    for(int i = 0;i < (int)b.size();i ++)
    {
        int r = i + k - 1;
        if(r >= b.size()) break;
        if(i == 0)
        {
            if(r + 1 >= 0 && r + 1 < b.size())
                ans = max(ans,b[r + 1] - 1);
        }
        else if(r == (int)b.size() - 1)
        {
            if(i - 1 >= 0)
                ans = max(ans,n - (b[i - 1] + 1) + 1);
        }
        else
        {
            if(r + 1 >= 0 && r + 1 < b.size() && i - 1 >= 0)
                ans = max(ans,(b[r + 1] - 1) - (b[i - 1] + 1) + 1);
        }
    }
    if(a.size() <= k || b.size() <= k)
        ans = n;
    printf("%d",ans);
    return 0;
}


D

题意:n*m的迷宫,每个格子有四面,每一面都有可能有门,这样一共是16种格子。每分钟你可以从一个格子透过门走到另一个相邻的格子,要求两个格子都有相应的门;或者人原地不动,所有的格子原地瞬时针旋转90度。问给定起点到给定终点的最短路。

n<=m<=1000

SB分层图BFS,代码神烦

边数在全都是四连通的时候达到最大,大概边要达到一千多万,数组开2000w比较保险

数组开小他说我TLE,我以为On算法被卡常,调了半天……

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

typedef long long LL;
const int SZ = 4000010;
const int INF = 1000000010;

int read()
{
    int n = 0;
    char a = getchar();
    bool flag = 0;
    while(a > '9' || a < '0') { if(a == '-') flag = 1; a = getchar(); }
    while(a >= '0' && a <= '9') { n = n * 10 + a - '0'; a = getchar(); }
    if(flag) n = -n;
    return n;
}

string mp[200];

const int dx[] = {0,1,0,-1};
const int dy[] = {1,0,-1,0};//右 下 左 上 

char maps[1010][1010];

int n,m;

bool iscan(int x,int y)
{
    return x >= 1 && x <= n && y >= 1 && y <= m;
}

int getnode(int x,int y,int d)
{
    return (x - 1) * m + y + (d - 1) * n * m; 
}

int head[SZ],nxt[20000000],tot = 1;

struct edge{
    int t;
    bool d;
}l[20000000];

void build(int f,int t,int d)
{
    l[++ tot] = (edge){t,d};
    nxt[tot] = head[f]; head[f] = tot;
}

bool vis[SZ];
struct haha{
    int u,d;
};
queue<haha> q;

int bfs(int s,int e)
{
    q.push((haha){s,0});
    vis[s] = 1;
    while(q.size())
    {
        haha f = q.front(); q.pop();
        for(int i = head[f.u];i;i = nxt[i])
        {
            int v = l[i].t;
            if(!vis[v])
            {
                vis[v] = 1;
                if(v == e) return f.d + l[i].d;
                q.push((haha){v,f.d + l[i].d});
            }
        }
    }
    return -1;
}

int main()
{
    mp['+'] = "1111";
    mp['-'] = "1010";
    mp['|'] = "0101";
    mp['^'] = "0001";
    mp['>'] = "1000";
    mp['<'] = "0010";
    mp['v'] = "0100";
    mp['L'] = "1101";
    mp['R'] = "0111";
    mp['U'] = "1110";
    mp['D'] = "1011";
    mp['*'] = "0000";
    n = read(),m = read();
    for(int i = 1;i <= n;i ++)
        gets(maps[i] + 1);
    int sx = read(),sy = read(),ex = read(),ey = read();
    for(int p = 1;p <= 4;p ++)
    {
        for(int i = 1;i <= n;i ++)
        {
            for(int j = 1;j <= m;j ++)
            {
                for(int k = 0;k < 4;k ++)
                {
                    int p1 = (k - (p - 1) + 4) % 4;
                    int p2 = (p1 + 2) % 4;
                    int x = i + dx[k],y = j + dy[k];
                    if(iscan(x,y))
                    {
                        if(mp[maps[i][j]][p1] == '1' && mp[maps[x][y]][p2] == '1')
                            build(getnode(i,j,p),getnode(x,y,p),1);//printf("%d %d %d %d %d %d %d %d\n",i,j,x,y,p1,p2,p,k);
                    }
                }
            }
        }
    }
    for(int i = 1;i <= n;i ++)
    {
        for(int j = 1;j <= m;j ++)
        {
            build(getnode(i,j,1),getnode(i,j,2),1);
            build(getnode(i,j,2),getnode(i,j,3),1);
            build(getnode(i,j,3),getnode(i,j,4),1);
            build(getnode(i,j,4),getnode(i,j,1),1);
        }
    }   
    int e = n * m * 4 + 1;
    build(getnode(ex,ey,1),e,0);
    build(getnode(ex,ey,2),e,0);
    build(getnode(ex,ey,3),e,0);
    build(getnode(ex,ey,4),e,0);
    printf("%d",bfs(getnode(sx,sy,1),e));
    return 0;
}
/*
2 3
<><
><>
1 1
1 1
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值