AtCoder Beginner Contest 430(ABCDEF)

前言

第一次赛时出E!!第一次rank进前一千!!!我就说之前是因为我生病状态不好()

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

/*   /\_/\
*   (= ._.)
*   / >  \>
*/

#define endl '\n'
#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) cout<<#a<<endl; for(auto x:a) cout<<x<<" ";cout<<endl
#define INF 1e9
#define INFLL 1e18
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int a,b,c,d;
    cin>>a>>b>>c>>d;

    if(c<a||c>=a&&d>=b)
    {
        cout<<"No"<<endl;
    }
    else
    {
        cout<<"Yes"<<endl;
    }
}

void init()
{
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t=1;
    //cin>>t;
    init();
    while(t--)
    {
        solve();    
    }
    return 0;
}

这个题就是根据化简后的条件判断一下即可,注意合法的时候要输出No()

二、B - Count Subgrid

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

/*   /\_/\
*   (= ._.)
*   / >  \>
*/

#define endl '\n'
#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) cout<<#a<<endl; for(auto x:a) cout<<x<<" ";cout<<endl
#define INF 1e9
#define INFLL 1e18
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int n,m;
    cin>>n>>m;
    vector<string>a(n);
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }

    set<string>st;
    for(int i=0;i<=n-m;i++)
    {
        for(int j=0;j<=n-m;j++)
        {
            string s;
            for(int l=i;l<i+m;l++)
            {
                for(int r=j;r<j+m;r++)
                {
                    s+=a[l][r];
                }
            }
            st.insert(s);
        }
    }

    cout<<st.size()<<endl;
}

void init()
{
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t=1;
    //cin>>t;
    init();
    while(t--)
    {
        solve();    
    }
    return 0;
}

因为数据范围不大,所以直接暴力枚举网格的两点往set里加即可。

三、C - Truck Driver

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

/*   /\_/\
*   (= ._.)
*   / >  \>
*/

#define endl '\n'
#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) cout<<#a<<endl; for(auto x:a) cout<<x<<" ";cout<<endl
#define INF 1e9
#define INFLL 1e18
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int n,a,b;
    cin>>n>>a>>b;
    string s;
    cin>>s;
    s=" "+s;

    ll ans=0;
    vector<int>pa;
    vector<int>pb;
    for(int i=1;i<=n;i++)
    {
        if(s[i]=='a')
        {
            pa.push_back(i);
        }
        else
        {
            pb.push_back(i);
        }

        int left=0;
        if(pb.size()>=b)
        {
            left=pb[pb.size()-b];
        }
        int right=0;
        if(pa.size()>=a)
        {
            right=pa[pa.size()-a];
        }

        if(left<right)
        {
            ans+=right-left;
        }
    }
    cout<<ans<<endl;
}

void init()
{
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t=1;
    //cin>>t;
    init();
    while(t--)
    {
        solve();    
    }
    return 0;
}

这个题肯定还是考虑固定右端点,然后去找所有合法的左端点。所以考虑分别记录每个a和b的出现位置,那么从当前点往左找b个b的位置就是左端点的最左边界,往左找a个a的位置就是左端点的最右边界,那么中间的每个位置都可以作为左端点产生贡献。

四、D - Neighbor Distance

set的二分真用不明白......

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

/*   /\_/\
*   (= ._.)
*   / >  \>
*/

#define endl '\n'
#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) cout<<#a<<endl; for(auto x:a) cout<<x<<" ";cout<<endl
#define INF 1e9
#define INFLL 1e18
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int n;
    cin>>n;
    vector<ll>a(n+1);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }

    set<ll>st;
    st.insert(0);

    map<ll,ll>dis;
    dis[0]=INFLL;
    for(int i=1;i<=n;i++)
    {
        dis[a[i]]=INFLL;
    }

    ll ans=dis[0];
    for(int i=1;i<=n;i++)
    {
        ll pos=a[i];

        st.insert(pos);

        auto pre=st.lower_bound(pos);
        pre=prev(pre);
        auto nxt=st.upper_bound(pos);

        if(nxt==st.end())
        {
            ans-=dis[*pre];
            dis[*pre]=min(dis[*pre],pos-*pre);

            dis[pos]=pos-*pre;
            ans+=dis[*pre]+dis[pos];
        }
        else
        {
            ans-=dis[*pre]+dis[*nxt];
            dis[*pre]=min(dis[*pre],pos-*pre);
            dis[*nxt]=min(dis[*nxt],*nxt-pos);

            dis[pos]=min(pos-*pre,*nxt-pos);
            ans+=dis[*pre]+dis[*nxt]+dis[pos];
        }

        cout<<ans<<endl;
    }
}

void init()
{
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t=1;
    //cin>>t;
    init();
    while(t--)
    {
        solve();    
    }
    return 0;
}

很容易可以注意到,在一个位置插入一个人,可能影响的只有其相邻的两人。所以考虑直接用一个set维护目前的所有人,然后每次去二分前一个人和后一个人,只对这两个人进行修改即可。

五、E - Shift String

现在也就写写板题了......

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

/*   /\_/\
*   (= ._.)
*   / >  \>
*/

#define endl '\n'
#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) cout<<#a<<endl; for(auto x:a) cout<<x<<" ";cout<<endl
#define INF 1e9
#define INFLL 1e18
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const int base=499;

const int MAXN=1e6+6;

vector<ll>power(MAXN);

ll subHash(int l,int r,vector<ll>&hash)
{
    ll ans=hash[r];
    if(l>1)
    {
        ans-=hash[l-1]*power[r-l+1];
    }
    return ans;
}

void solve()
{
    string a,b;
    cin>>a>>b;
    int n=a.length();

    a=" "+a;
    b=" "+b;

    vector<ll>hash1(n+1);
    vector<ll>hash2(n+1);
    for(int i=1;i<=n;i++)
    {
        hash1[i]=hash1[i-1]*base+a[i]-'a'+1;
        hash2[i]=hash2[i-1]*base+b[i]-'a'+1;
    }

    if(hash1[n]==hash2[n])
    {
        cout<<0<<endl;
        return ;
    }

    for(int i=1;i<=n;i++)
    {
        if(subHash(1,i,hash1)==subHash(n-i+1,n,hash2)&&subHash(i+1,n,hash1)==subHash(1,n-i,hash2))
        {
            cout<<i<<endl;
            return ;
        }
    }   
    cout<<-1<<endl;
}

void init()
{
    power[0]=1;
    for(int i=1;i<MAXN;i++)
    {
        power[i]=power[i-1]*base;
    }
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    init();
    while(t--)
    {
        solve();    
    }
    return 0;
}

这个题其实看到的第一眼就能发现是字符串哈希的板题。不难发现,当把A串若干个字符移动到后面之后,若此时能和B串匹配,那么就说明A串原始的后部分和B串前部分一样,A串原始的前部分和B串的后部分一样。那么为了快速匹配两字符串,就可以使用字符串哈希,之后枚举一下A串把哪些字符移动到后面即可。

六、F - Back and Forth Filling

群友是怎么想到这个思路的......

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

/*   /\_/\
*   (= ._.)
*   / >  \>
*/

#define endl '\n'
#define dbg(x) cout<<#x<<" "<<x<<endl
#define vdbg(a) cout<<#a<<endl; for(auto x:a) cout<<x<<" ";cout<<endl
#define INF 1e9
#define INFLL 1e18
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    int n;
    cin>>n;
    string s;
    cin>>s;
    s=" "+s;

    vector<vector<int>>g(n+1);
    vector<int>deg(n+1);
    for(int i=1;i<n;i++)
    {
        if(s[i]=='L')
        {
            g[i+1].push_back(i);
            deg[i]++;
        }
        else
        {
            g[i].push_back(i+1);
            deg[i+1]++;
        }
    }

    queue<int>q;
    for(int i=1;i<=n;i++)
    {
        if(deg[i]==0)
        {
            q.push(i);
        }
    }

    vector<int>left(n+1);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();

        for(auto v:g[u])
        {
            left[v]+=left[u]+1;
            if(--deg[v]==0)
            {
                q.push(v);
            }
        }
    }

    for(int i=1;i<=n;i++)
    {
        g[i].resize(0);
    }
    deg.resize(n+1);
    for(int i=1;i<n;i++)
    {
        if(s[i]=='R')
        {
            g[i+1].push_back(i);
            deg[i]++;
        }
        else
        {
            g[i].push_back(i+1);
            deg[i+1]++;
        }
    }

    for(int i=1;i<=n;i++)
    {
        if(deg[i]==0)
        {
            q.push(i);
        }
    }

    vector<int>right(n+1);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();

        for(auto v:g[u])
        {
            right[v]+=right[u]+1;
            if(--deg[v]==0)
            {
                q.push(v);
            }
        }
    }

    vector<int>ans(n+2);
    for(int i=1;i<=n;i++)
    {
        int l=1+left[i];
        int r=n-right[i];

        ans[l]++;
        ans[r+1]--;
    }

    for(int i=1;i<=n;i++)
    {
        ans[i]+=ans[i-1];
    }

    for(int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    cout<<endl;
}

void init()
{
}

signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int t=1;
    cin>>t;
    init();
    while(t--)
    {
        solve();    
    }
    return 0;
}

这个题直接就是注意到每个数字的左右关系可以形成一张有向图,那么就可以在这张有向图上进行拓扑排序,统计出每个数字可以存在的位置区间,然后根据每个数的区间差分一下求前缀和即可。因为同时存在左右关系,所以需要建正反图分别跑一遍拓扑排序。

这种拓扑排序的题多少得对这种关系很敏感才能注意到......

总结

再接再厉,加油!

END

相关推荐
小肖爱笑不爱笑3 小时前
2025/11/5 IO流(字节流、字符流、字节缓冲流、字符缓冲流) 计算机存储规则(ASCII、GBK、Unicode)
java·开发语言·算法
Elias不吃糖3 小时前
第四天学习总结:C++ 文件系统 × Linux 自动化 × Makefile 工程化
linux·c++·学习
熬了夜的程序员3 小时前
【LeetCode】99. 恢复二叉搜索树
算法·leetcode·职场和发展
Kent_J_Truman3 小时前
LeetCode Hot100 自用
算法·leetcode·职场和发展
还是码字踏实3 小时前
算法题种类与解题思路全面指南:基于LeetCode Hot 100与牛客Top 101
算法·leetcode
沐怡旸3 小时前
【穿越Effective C++】条款14:在资源管理类中小心copying行为——RAII类的拷贝语义设计
c++·面试
AA陈超3 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P07-06 能力输入的回调
c++·游戏·ue5·游戏引擎·虚幻
Victory_orsh4 小时前
“自然搞懂”深度学习(基于Pytorch架构)——010203
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
CoovallyAIHub4 小时前
突破360°跟踪极限!OmniTrack++:全景MOT新范式,HOTA指标狂飙43%
深度学习·算法·计算机视觉