1. 程式人生 > >Educational Codeforces Round 55 (Rated for Div. 2) ABCD總結

Educational Codeforces Round 55 (Rated for Div. 2) ABCD總結

終測前三題900+,終測完三題597,上了35分。總算突破了1700。。。

這次題目簡單題來說偏難。A題9分鐘才寫出來。賽後補了D發現並不是太難。。。

A:一本書有n頁,你現在在x頁,你要翻到y頁,一次只能翻正好d頁。可以從第x頁翻到第n頁或者第1頁(即使不夠正好d頁),再翻到第y頁。不能翻到第y頁輸出-1,否則輸出最少翻幾次。

只需要分上面三種情況看能否整除取最小值就好了。如果都不能整除就是-1。

B:給你一個只包含'G'和'S'的串,你只能最多交換一次兩個字母的位置。求最長連續G序列多長。

統計一下G的總數,維護一下每一個S前面連續多少個G,後面連續多少個G,然後O(n)掃一遍,對於S,考慮能否交換使其左右連線起來。(注意這裡是兩種情況。)

C:有n個學生,m個課題。給你每個學生所選的課題的編號和能力值。

你要選若干學生,組成人數相同的若干組,每一組學生所選課題相同,且任意兩組的課題不能相同。求滿足要求的總最大能力值。

用vector儲存每個課題的學生的能力值,排序,預處理字尾最大值,列舉每一組學生的總數,然後人數夠且字尾>0的課題就可以選了。比賽的時候讀錯題了,以為每組不超過m個人,害我調了一個小時。。。

D:給你n個整數d[i]>=1,這n個點依次編號1~n,讓你構造一個圖,使

1、這個圖的直徑最大

2、這個圖連通

3、這n個點的度數都不超過其對應的d[i]

顯然儘可能的直徑最大,就是先把度不為1的點連成一條鏈,然後度為1的點可以接在兩頭,這樣直徑肯定最大。

然後多餘的度為1的點連到度數還沒夠的點,看看能不能全連上即可。

因此用三個vector,第一個vector儲存度為1的點的下標,第二個第三個都是pair,分別儲存度和下標,以及相連的點的編號,然後按上面思路寫就行了。注意no情況的判斷。

程式碼:

#include<bits/stdc++.h>
#define ll long long
#define mp make_pair
using namespace std;
const int maxn=500+10;
int n,k;
vector<int>yi;
vector< pair<int,int> >duo,ans;
int cnt,tmp,flag;
int d[maxn];
int main()
{

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&k);
        if(k==1) yi.push_back(i);
        else duo.push_back(mp(k,i));
    }
    if(!duo.size()) {puts("NO");return 0;}
    tmp=duo.size()-1;
    for(int i=0;i<duo.size()-1;i++)
    {
        ans.push_back(mp(duo[i].second,duo[i+1].second));
        d[duo[i].second]++;
        d[duo[i+1].second]++;
    }
    if(yi.size())
    {
        ans.push_back(mp(yi.back(),duo[0].second));
        d[yi.back()]++;
        d[duo[0].second]++;
        yi.pop_back();
        tmp++;
        if(yi.size())
        {
        ans.push_back(mp(yi.back(),duo.back().second));
        d[yi.back()]++;
        d[duo.back().second]++;
        yi.pop_back();
        tmp++;
        }
    }
    int i=0;
    while(yi.size()&&i<duo.size())
    {
        if(d[duo[i].second]<duo[i].first)
        {
            ans.push_back(mp(yi.back(),duo[i].second));
            d[duo[i].second]++;
            yi.pop_back();
        }
        else i++;
    }
    if(yi.size()) {puts("NO");return 0;}
    printf("YES %d\n",tmp);
    printf("%d\n",ans.size());
    for(int i=0;i<ans.size();i++)
    {
        printf("%d %d\n",ans[i].first,ans[i].second);
    }
    return 0;
}