Codeforces Round #756 (Div. 3)

Codeforces Round #756 (Div. 3)

A. Make Even

分析:

  • 0 , 1 , 2 , − 1 0,1,2,-1 0,1,2,1 四种情况
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e6+5;
char s[N];
signed main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>s+1;
        int n=strlen(s+1);
        int ans=0,fg=0;
        if((s[n]&1)==0) cout<<"0\n";
        else 
        {
            if((s[1]&1)==0) cout<<"1\n"; // 头为偶数
            else 
            {
                for(int i=1;i<=n;i++)
                {
                    if((s[i]&1)==0) 
                    {
                        fg=1; break;
                    }
                }
                if(fg) cout<<"2\n"; //中间有偶数,先将偶数反转到第一位,再从头到尾,2步
                else cout<<"-1\n";
            }
        }
    }
}

B. Team Composition: Programmers and Mathematicians

  • 小学数学
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e6+5;
char s[N];
signed main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int a,b;
        cin>>a>>b;
        if(a>b) swap(a,b);
        cout<<min(a,(a+b)/4)<<endl;
    }
}

C. Polycarp Recovers the Permutation

分析:

  • 构造题

  • 首先,最大的数在新数组中一定是第 1 个或第 n 个(即头或尾)

  • 假设在原数组中,最大的在左端,那么构造新数组时,就是原数组的倒置

    所以,将新数组倒置就是原数组

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e6+5;
int a[N],p[N];
void solve()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    if(a[1]==n || a[n]==n)
    {
        for(int i=n;i>=1;i--) cout<<a[i]<<' '; 
        cout<<"\n";
    }
    else cout<<"-1\n";
}
signed main()
{
    ios::sync_with_stdio(0);
    int T;
    cin>>T;
    while(T--) solve();
}

D. Weights Assignment For Tree Edges

分析:

  • 构造题

  • 要使 n 条边权的大小按一定顺序(根为0),从 1 到 n 按顺序赋值给 n 个点即可

    最后要输出的 ans 即,当前点的点权 - 其父亲点权 = 该点边权

  • -1 的情况,就是按顺序轮到某一点,但是其父亲还未被赋值,即:根越过父亲直接到儿子了,显然不成立

#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int N=1e6+5;
int a[N],p[N];
int ans[N];
void solve()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i], ans[i]=0;
    for(int i=1;i<=n;i++) cin>>p[i];
    if(p[1]!=a[p[1]]) cout<<"-1\n";
    else 
    {
        ans[p[1]]=1;
        for(int i=2;i<=n;i++)
        {
            if(!ans[a[p[i]]])
            {
                cout<<"-1\n"; 
                return ;
            }
            ans[p[i]]=i;
        }
        for(int i=1;i<=n;i++) cout<<ans[i]-ans[a[i]]<<' '; 
        cout<<"\n";
    }
}
signed main()
{
    ios_base::sync_with_stdio(0);
    int T;
    cin>>T;
    while(T--) solve();
}

E1. Escape The Maze (easy version)

分析:

  • 多源点同时覆盖

  • 所有 x i x_i xi (还有 根1)同时向四面八方覆盖

    若最后 根1 能到达某一个叶子节点,输出 “YES” 即可

  • 注意:

    if(pr[u]==1 && g[u].size()==1 && u!=1) 中的 u!=1 不要忘记
    
#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int N=1e6+5;
int x[N];
vector <int> g[N];
int n,k;
int vis[N],pr[N]; // pr存从哪一点出发
bool bfs()
{
    queue <int> q;
    for(int i=1;i<=k;i++)  
    {
        vis[x[i]]=1;
        q.push(x[i]);
    }
    q.push(1); // 这个一定要在所有 xi 入队之后再入队,不然由于 ”时间差“ 会错
    vis[1]=1;
    pr[1]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(pr[u]==1 && g[u].size()==1 && u!=1) // 从 1 成功到达某一个叶子
        {   
            return 1;
        }
        for(int v : g[u])
        {
            if(!vis[v])
            {
                vis[v]=1;
                q.push(v);
                pr[v]=pr[u];
            }
        }
    }
    return 0;
}
void solve()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) vis[i]=pr[i]=0, g[i].clear();
    for(int i=1;i<=k;i++) cin>>x[i];
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    if(bfs()) cout<<"YES\n";
    else cout<<"NO\n";
}
signed main()
{
    ios_base::sync_with_stdio(0);
    int T;
    cin>>T;
    while(T--) solve();
}

E2. Escape The Maze (hard version)

分析

  • 同上题的区别:让统计最少需要多少人

  • 只需考虑 根1 在覆盖过程中能遇到的点即可,放在 set 再去重,返回 size 即可

  • 注意:

    if(pr[u]==1 && pr[v]!=1) se.insert(pr[v]); 不要少了 pr[v]!=1
    
#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int N=1e6+5;
int x[N];
vector <int> g[N];
int n,k;
int vis[N],pr[N];
set <int> se;
int bfs()
{
    queue <int> q;
    for(int i=1;i<=k;i++)  
    {
        vis[x[i]]=1;
        q.push(x[i]);
        pr[x[i]]=x[i];
    }
    q.push(1);
    vis[1]=1;
    pr[1]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        if(pr[u]==1 && g[u].size()==1 && u!=1)
        {
            return -1;
        }
        for(int v : g[u])
        {
            if(!vis[v])
            {
                vis[v]=1;
                q.push(v);
                pr[v]=pr[u];
            }
            else 
            {
                if(pr[u]==1 && pr[v]!=1) se.insert(pr[v]); // 注意点
            }
        }
    }
    return se.size();
}
void solve()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) vis[i]=pr[i]=0, g[i].clear();
    se.clear();
    for(int i=1;i<=k;i++) cin>>x[i];
    for(int i=1;i<n;i++)
    {
        int u,v;
        cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    int ans=bfs();
    cout<<ans<<"\n";
}
signed main()
{
    ios_base::sync_with_stdio(0);
    int T;
    cin>>T;
    while(T--) solve();
}

F. ATM and Students

分析:

  • 双指针板子题
#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int N=1e6+5;
int a[N];
int n,k;
void solve()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    int l=1,r=0,ans=0,t=k,anl,anr;
    while(l<=n && r<=n)
    {
        if(t>=0) 
        {
            if(r-l+1>ans)
            {
                ans=r-l+1;
                anl=l; anr=r;
            }
            t+=a[++r];
        }
        else 
        {
            t-=a[l++];
        }
    }
    if(ans>0) cout<<anl<<' '<<anr<<"\n";
    else cout<<"-1\n";
}
signed main()
{
    ios_base::sync_with_stdio(0);
    int T;
    cin>>T;
    while(T--) solve();
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yezzz.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值