The 2021 CCPC Guilin Onsite (Grand Prix of EDG)(部分补题)

A.Hero Named Magnus

链接.

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t;
ll x;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--)
    {
        cin>>x;
        cout<<x-1+x<<"\n";
    }
    return 0;
}

I. PTSD

链接.


#include<bits/stdc++.h>
#define ll long long
using namespace std;
 
int t;
int n;
char s[1000010];
 
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
 
    cin>>t;
    while(t--)
    {
        cin>>n>>s;
        ll ans=0,k=0;
        for(int i=n-1;i>=0;i--)
        {
            if(s[i]=='0')k++;
            else
            {
                if(k>0)ans+=i+1,k--;
                else k++;
            }
        }
        cout<<ans<<"\n";
    }
 
    return 0;
}

G. Occupy the Cities

链接.
思路:二分找出每个0到其最近的1的距离,记录这些距离的最大值maxn及产生最大值的0的位置,遍历这些0,看是否有无两个0共用一个1,若有maxn++。maxn即为所求。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
 
int t;
int n;
char s[1000010];
int a[1000010];
int f[1000010];
vector<int>v;
 
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
 
    cin>>t;
    while(t--)
    {
        v.clear();
        cin>>n>>s;
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='1')a[cnt++]=i,f[i]=0;
        }
        int maxn=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='1')continue;
            if(i>a[cnt-1])
            {
                if(i-a[cnt-1]>maxn)
                {
                    v.clear();
                    maxn=i-a[cnt-1];
                    v.push_back(i);
                }
                else if(i-a[cnt-1]==maxn)
                {
                    v.push_back(i);
                }
                continue;
            }
 
            int l=0,r=cnt-1;
            while(l<r)
            {
                int mid=l+(r-l)/2;
                if(a[mid]>=i)r=mid;
                else l=mid+1;
            }
            int x=a[l]-i;
            if(l-1>=0)x=min(x,i-a[l-1]);
            if(x>maxn)
            {
                v.clear();
                v.push_back(i);
                maxn=x;
            }
            else if(x==maxn)
            {
                v.push_back(i);
            }
        }
 
        int flag=0;
        for(int j=0;j<v.size();j++)
        {
            int i=v[j];
            if(i-maxn>=0&&s[i-maxn]=='1'&&i+maxn<n&&s[i+maxn]=='1')
            {
                if(f[i-maxn]<=f[i+maxn])f[i-maxn]++;
                else f[i+maxn]++;
            }
            else if(i-maxn>=0&&s[i-maxn]=='1')f[i-maxn]++;
            else if(i+maxn<n&&s[i+maxn]=='1')f[i+maxn]++;
            if((i-maxn>=0&&f[i-maxn]>1)||(i+maxn<n&&f[i+maxn]>1))flag=1;
            if(flag)break;
        }
        if(flag)maxn++;
 
        cout<<maxn<<"\n";
    }
 
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
int t;
int n;
char s[1000010];
int a[1000010],f[1000010];
vector<int>v;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>t;
    while(t--)
    {
        v.clear();
        cin>>n>>s;
        for(int i=0;i<n;i++)
        {
            a[i]=f[i]=0;
            if(s[i]=='1')v.push_back(i);
        }
        int maxn=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='0')
            {
                int l=0,r=v.size()-1;
                if(i<v[0])
                {
                    a[i]=abs(i-v[0]);
                    maxn=max(maxn,a[i]);
                }
                else if(i>v[r])
                {
                    a[i]=abs(i-v[r]);
                    maxn=max(maxn,a[i]);
                }
                else
                {
                    while(l<r)
                    {
                        int mid=l+(r-l)/2;
                        if(v[mid]>=i)r=mid;
                        else l=mid+1;
                    }
                    a[i]=min(abs(v[l]-i),abs(v[l-1]-i));
                    maxn=max(maxn,a[i]);
                }
            }
        }
        int ans=maxn;
        for(int i=0;i<n;i++)
        {
            if(a[i]==maxn)
            {
                if(i-maxn>=0&&s[i-maxn]=='1')
                {
                    if(f[i-maxn]==0)
                    {
                        f[i-maxn]=1;
                    }
                    else
                    {
                        if(i+maxn<n&&s[i+maxn]=='1')
                        {
                            f[i+maxn]=1;
                        }
                        else
                        {
                            ans++;
                            break;
                        }
                    }
                }
                else
                {
                    if(f[i+maxn]==1)
                    {
                        ans++;
                        break;
                    }
                    else f[i+maxn]=1;
                }
            }
        }
        cout<<ans<<"\n";
    }
    return 0;
}

D. Assumption is All You Need

链接.
+题意:给两个1-n的排列A和B,问是否可以通过交换把A变成B,若可以请输出总交换次数和每次交换的下标,不可以输出-1。(交换:若i<j,ai>aj,则可以交换)。
思路:a记录排列A,c记录排列A中的1-n的位置,b记录排列B中的1-n的位置。
若ci<bi,则一定不可以交换.
可以交换时,遍历b[i]-c[i]区间中值从小到大交换。

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

int t;
int n,a[2050],b[2050],c[2050],d[2050];
vector<PII>v;

int main()
{
    ios::sync_with_stdio(0);
    //cin.tie(0);cout.tie(0);

    cin>>t;
    while(t--)
    {
        v.clear();
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            c[a[i]]=i;
        }
        for(int j=1;j<=n;j++)
        {
            int x;cin>>x;
            d[j]=x;
            b[x]=j;
        }

        int flag=1;
        for(int i=1;i<=n;i++)
        {
            if(c[i]==b[i]);
            else if(c[i]<b[i])
            {
                flag=0;
                break;
            }
            else
            {
                for(int j=i+1;j<=n;j++)
                {
                    if(c[j]<c[i]&&c[j]>=b[i])
                    {
                        v.push_back({c[j],c[i]});
                        swap(a[c[i]],a[c[j]]);
                        swap(c[i],c[j]);
                    }
                    if(c[i]==b[i])break;
                }
                if(c[i]!=b[i])
                {
                    flag=0;
                    break;
                }
            }
        }

        if(flag)
        {
            cout<<v.size()<<"\n";
            for(int i=0;i<v.size();i++)
            {
                cout<<v[i].first<<" "<<v[i].second<<"\n";
            }
        }
        else cout<<"-1\n";
    }
    return 0;
}

E. Buy and Delete

链接.
让fw认识到自己数论不会图论不会啥都不会…
思路:
若有环<=c,则为2;
若只有边<=c,则为1;
否则为0;

#include<bits/stdc++.h>
#define ll long long
#define pii pair<ll,int>
#define inf 0x3f3f3f3f
using namespace std;

int n,m;
ll c;

int idx=0;
struct edge
{
    int to,nxt;
    ll val;
}e[5010];
int head[5010];
void add(int a,int b,int c)
{
    e[idx].to=b;
    e[idx].val=c;
    e[idx].nxt=head[a];
    head[a]=idx++;
}

int vis[2010];
ll dist[2010];
priority_queue<pii,vector<pii>,greater<pii> >q;
bool dij(int s)
{
    for(int i=1;i<=n;i++)vis[i]=0,dist[i]=inf;
    dist[s]=0;
    q.push({0,s});
    while(!q.empty())
    {
        int x=q.top().second;
        ll y=q.top().first;
        q.pop();
        if(vis[x])continue;
        vis[x]=1;
        for(int i=head[x];i!=-1;i=e[i].nxt)
        {
            int v=e[i].to;
            if(v==s&&dist[x]+e[i].val<=c)return 1;
            if(dist[v]>dist[x]+e[i].val)
            {
                dist[v]=dist[x]+e[i].val;
                q.push({dist[v],v});
            }
        }
    }
    return 0;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    memset(head,-1,sizeof head);

    int ans=0;
    cin>>n>>m>>c;
    while(m--)
    {
        int u,v,w;
        cin>>u>>v>>w;
        add(u,v,w);
        if(w<=c)ans=1;
    }

    if(!ans)
    {
        cout<<"0\n";
        return 0;
    }

    for(int i=1;i<=n;i++)
    {
        if(dij(i))
        {
            ans++;
            break;
        }
    }
    cout<<ans<<"\n";
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值