Codeforces Round #550 A B C D E F

A題:給一個字符串,問字符串內字母是否是唯一且能夠排列成連續的。
直接sort一遍然後順序遍歷看之前的每個字母和之前那個是否連續【即a[i-1]==a[i]-1?】

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=100+7;
int n;
int main()
{
    char tmp[maxn];
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",tmp);
        bool ans=true;
        sort(tmp,tmp+strlen(tmp));
        for(int i=1;i<strlen(tmp);i++)
        {
            if(tmp[i]==tmp[i-1]+1)continue;
            else
            {
                ans=false;
                break;
            }
        }
        printf("%s\n",ans?"Yes":"No");
    }
}

B給一個序列,按照 -奇-偶 或 -偶-奇 的順序刪除數字,問刪除到不能刪除時剩下數的最小總和是多少
首先統計一下數字奇偶各多少,若差值小於等於1說明是可以徹底刪完的。若刪不完,那麼剩下的肯定是多出來的奇數或偶數,那麼排序之後取最小的幾個奇數或者偶數求和即可。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=2000+7;
int n;
int a[maxn];
int main()
{
    scanf("%d",&n);
    int o=0,e=0;
    for(int i=0; i<n; i++)
    {
        scanf("%d",&a[i]);
        if(a[i]&1)o++;
        else e++;
    }
    if(abs(o-e)<=1)
    {
        printf("0\n");
        return 0;
    }
    sort(a,a+n);
    int ans=0;
    if(e>o)
    {
        int tmp=e-o-1;
        int i=0;
        while(tmp>0&&i<n)
        {
            if(!(a[i]&1))ans+=a[i],tmp--;
            i++;
        }
    }
    else
    {
        int tmp=o-e-1;
        int i=0;
        while(tmp>0&&i<n)
        {
            if(a[i]&1)ans+=a[i],tmp--;
            i++;
        }
    }
    printf("%d\n",ans);
}

C有倆嚴格遞增和嚴格遞減的序列,將這倆序列合成到一起,現在給你合成的序列,問該序列是否是由兩個嚴格遞增和遞減的序列生成的,是的話輸出倆序列
給序列排序,輸入時預處理好每個數字的出現次數,可以知道出現超過2次的,一定有一個序列出現過多次,那麼表示一定不是嚴格遞增或遞減的,那麼直接輸出NO,否則,順序遍歷排序好的序列,沒出現過的數字扔到遞增序列,遇到一個重複出現的數字扔到遞減序列,最後正序輸出遞增,逆序輸出遞減即可

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=2e5+7;
int n;
int a[maxn];
short int vis[maxn];
int main()
{
    scanf("%d",&n);
    bool flag=true;
    for(int i=0; i<n; i++)
    {
        scanf("%d",&a[i]);
        vis[a[i]]++;
        if(vis[a[i]]>=3)flag=false;
    }
    if(!flag)
    {
        printf("NO\n");
        return 0;
    }
    vector<int>up,down;
    sort(a,a+n);
    for(int i=0; i<n; i++)
    {
        if(i==0)up.push_back(a[i]);
        else
        {
            if(a[i]>up.back())up.push_back(a[i]);
            else down.push_back(a[i]);
        }
    }
    printf("YES\n");
    printf("%d\n",up.size());
    if(up.size()==0)printf("\n");
    else
    {
        for(int i=0; i<up.size(); i++)printf("%d%c",up[i],i==up.size()-1?'\n':' ');
    }
    printf("%d\n",down.size());
    if(down.size()==0)printf("\n");
    else
    {
        for(int i=down.size()-1; i>=0; i--)printf("%d%c",down[i],i==0?'\n':' ');
    }
}

D給一個序列,有倆操作,對兩個相鄰的數字,可以讓小的值加上兩數差值使其相等,也能讓大的值減少兩者差值使其相等,問最少要做多少次操作可以使整個序列的值相等。
可以知道的是,這樣的操作一定能讓整個序列的值相等,然後就是,這樣的操作是具有傳遞性的,那麼我們一定是指定了某個數,然後從左到右或從右到左擴散開來這樣賦值,如何操作纔是步數最少的,明顯是讓剩下的數都等於開始序列中存在數量最多的數,操作次數是最小的。因此輸入時找到出現次數最多的數,記錄該數出現的任意一個位置,以該位置爲起點左右擴散並輸出結果即可。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=2e5+7;
int n;
int a[maxn];
int cnt[maxn];
int main()
{
    scanf("%d",&n);
    int maxcnt=0;
    int maxnum=0;
    int index=0;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        cnt[a[i]]++;
        if(cnt[a[i]]>maxcnt)maxcnt=cnt[a[i]],maxnum=a[i],index=i;
    }
    printf("%d\n",n-maxcnt);
    for(int i=index; i>=1; i--)
    {
        if(a[i]==maxnum)continue;
        int t;
        if(a[i]>maxnum)t=2;
        else t=1;
        printf("%d %d %d\n",t,i,i+1);
    }
    for(int i=index; i<=n; i++)
    {
        int t;
        if(a[i]==maxnum)continue;
        if(a[i]>maxnum)t=2;
        else t=1;
        printf("%d %d %d\n",t,i,i-1);
    }
}

E兩個等長字符串,字符串只用小寫字母構成,第一個字符串字典序嚴格小於第二個字符串,輸出按字典序排列下兩串的中位串。
若按數字全排列來說,那麼兩串相隔距離的中間位置串即中位數,換成字母也是如此,即26個字母是26進制的中位數。想想在十進制下是如何計算中位數,(左邊界+右邊界)/2,那麼此處也是這樣,從低位到高位模擬26進制加法和除法。當同位兩數加和是偶數時,中位數除2即可,若是奇數,那麼該位餘1,並借位給低位,那麼低位是已經做了除2計算的,因此低位借位到的1不當26處理,而當13處理,並加到低位上,於是當前高位可以直接除2,而低位借位後重新計算是否需要進位,並對26取模。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=2e5+7;
int main()
{
    int n;
    char a[maxn],b[maxn],ans[maxn];
    scanf("%d%s%s",&n,a,b);
    for(int i=n-1;i>=0;i--)
    {
        char mid=(a[i]+b[i])-194;
        if(mid&1)
        {
            ans[i+1]-='a';
            ans[i+1]+=13;
            ans[i]=(mid-1)>>1;
            ans[i]+=ans[i+1]/26;
            ans[i]+='a';
            ans[i+1]%=26;
            ans[i+1]+='a';
        }
        else ans[i]=mid/2+'a';
    }
    ans[n]='\0';
    printf("%s\n",ans);
}

F給n個點和m條邊,每條邊都是有向的,輸入構成一個圖,現在要求改變圖中有向邊的指向,問能否構成一個從任何點出發,路徑長度都小於等於1的有向圖。若可以輸出YES,並給出m條邊的指向,若與輸入時指向一樣則輸出0,否則爲1。若該圖不能構成任何路徑都爲1的有向圖輸出NO
跑一個BFS,得到到達每個節點的時間戳,若兩個存在有向邊的節點間時間戳 都爲偶數,說明比不滿足路徑長度小於等於1的條件。直接返回false,否則一定有解,根據每個節點的時間戳對節點進行01染色

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=2e5+7;
int n,m;
struct edge
{
    int id,from,to;
    edge(){}
    edge(int a,int b,int c)
    {
        id=a,from=b,to=c;
    }
}a[maxn];

vector<edge>mp[maxn];
int dis[maxn];
bool bfs()
{
    memset(dis,0x3f,sizeof dis);
    queue<pair<int,int> >q;
    q.push(make_pair(1,0));
    while(!q.empty())
    {
        pair<int,int> top=q.front();
        q.pop();
        for(int i=0;i<mp[top.first].size();i++)
        {
            edge tmp=mp[top.first][i];
            if(dis[tmp.to]>=0x3f3f3f3f)
            {
                dis[tmp.to]=top.second+1;
                q.push(make_pair(tmp.to,dis[tmp.to]));
            }
            else if(dis[tmp.to]%2==top.second%2)return false;
        }
    }
    return true;
}
int main()
{
    char ans[maxn];
    bool flag=true;
    int from,to;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&from,&to);
        a[i]=edge(i,from,to);
        mp[from].push_back(edge(i,from,to));
        mp[to].push_back(edge(i,to,from));
    }
    if(!bfs()) printf("NO\n");
    else
    {
        printf("YES\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<mp[i].size();j++)
            {
                edge tmp=mp[i][j];
                if(tmp.from==a[tmp.id].from)ans[tmp.id]=dis[i]%2?'0':'1';
                else ans[tmp.id]=dis[i]%2?'1':'0';
            }
        }
        ans[m+1]='\0';
        puts(ans+1);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章