[Codeforces Round #617 (Div. 3)] 題解 A,B,C,D,E1,E2,F


[Codeforces Round #617 (Div. 3)] 題解 A,B,C,D,E1,E2,F

1296A - Array with Odd Sum

思路:

如果一開始數組的sum和是奇數,那么直接YES,

否則:如果存在一個奇數和一個偶數,答案為YES,否則為NO

代碼:

int n;
int a[maxn];
 
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int t;
    t = readint();
    while (t--)
    {
        n = readint();
        int sum = 0;
        repd(i, 1, n) {
            a[i] = readint();
            sum += a[i];
        }
        if (sum & 1)
        {
            printf("YES\n");
        } else
        {
            int isok1 = 0;
            int isok2 = 0;
            repd(i, 1, n)
            {
                if (a[i] & 1)
                {
                    isok1 = 1;
                } else
                {
                    isok2 = 1;
                }
            }
            if (isok2 == 1 & isok1 == 1)
            {
                printf("YES\n");
            } else
            {
                printf("NO\n");
            }
        }
    }
 
    return 0;
}

B. Food Buying

思路:

直接貪心思想模擬即可,

如果 s>9,那么花掉 \(s-s mod 10\) 的錢,還剩下 s%10+s/10 ,繼續迭代。

否則 直接花掉所有錢,剩下0元,結束。

Time complexity: \(O(log_{10}(s))\)per test case.

代碼:

 
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int t;
    t = readint();
    int s;
    int ans;
    while (t--)
    {
        s = readint();
        ans = 0;
        while (s)
        {
            if (s > 9)
            {
                ans += s / 10 * 10;
                s = (s % 10) + (s / 10);
            } else
            {
                ans += s;
                s = 0;
            }
        }
        printf("%d\n", ans );
    }
 
    return 0;
}

C. Yet Another Walking Robot

思路:

題目讓刪除一個長度最小的子串使機器人最后的位置不變,即如果機器人單獨執行刪除的子串的話,首尾位置不變。

我們設機器人的在接到第i個指令后的位置是\((xi,yi)\),用map查找下之前有沒有出現過該位置。

如果有,令j = map[\((xi,yi)\)] ,那么 \([j+1,i]\) 這段子串就符合條件,維護出長度最小的符合條件的子串即可。同時用map記錄(或者是更新)下位置\((xi,yi)\) -> i

map是STL中的一個容器,std::map for C++

我的代碼中 map存的\((xi,yi)\) 對應的是i+1,這樣在維護答案時更方便。

Time complexity: \(O(nlogn)\) per test case.

代碼:

int n;
char s[maxn];
map<pii, int> m;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    int t;
    t = readint();
    while (t--)
    {
        n = readint();
        m.clear();
        scanf("%s", s + 1);
        int x = 0;
        int y = 0;
        int len = inf;
        int l, r;
        m[mp(0, 0)] = 1;
        repd(i, 1, n)
        {
            if (s[i] == 'L')
            {
                x--;
            } else if (s[i] == 'R')
            {
                x++;
            } else if (s[i] == 'U')
            {
                y++;
            } else
            {
                y--;
            }
            if (m.count(mp(x, y)))
            {
                int j = m[mp(x, y)];
                if (i - j + 1 < len)
                {
                    len = i - j + 1;
                    l = j;
                    r = i;
                }
            }
            m[mp(x, y)] = i+1;
        }
        if (len != inf)
            printf("%d %d\n", l, r);
        else {
            printf("-1\n");
        }
    }
    return 0;
}
 

D. Fight with Monsters

思路:

很明顯的,我們可以將每一個h[i]模去(a+b),得到新的h[i],如果它變成了零,讓“回滾”的一個輪回。

然后對於每一個怪獸,我們需要耗費\(\lceil\frac{h_i}{a}\rceil - 1\) 次魔法。

\(h[i] =\lceil\frac{h_i}{a}\rceil - 1\) 后,從小到大排個序后貪心取一下即可。

Time complexity: \(O(nlogn)\)

代碼:

int n;
ll a, b, k;
ll h[maxn];
ll c;
std::vector<ll> v;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    a = readll(); b = readll(); k = readll();
    c = a + b;
    repd(i, 1, n)
    {
        h[i] = readll();
    }
    int ans = 0;
    repd(i, 1, n)
    {
        h[i] %= c;
        if (h[i] == 0)
            h[i] += c;
        if (h[i] <= a)
        {
            ans++;
        } else
        {
            ll t = h[i] / a;
            if (h[i] % a != 0)
            {
                t++;
            }
            v.push_back(t - 1);
        }
    }
    sort(ALL(v));
    for (auto x : v)
    {
        if (x <= k)
        {
            ans++;
            k -= x;
        }
    }
    printf("%d\n", ans );
    return 0;
}

E1. String Coloring (easy version) /1296E2 - String Coloring (hard version)

思路:

解決本問題應該清楚 狄爾沃斯定理

百科的解釋為:

狄爾沃斯定理(Dilworth's theorem)亦稱偏序集分解定理,是關於偏序集的極大極小的定理,該定理斷言:對於任意有限偏序集,其最大反鏈中元素的數目必等於最小鏈划分中鏈的數目。此定理的對偶形式亦真,它斷言:對於任意有限偏序集,其最長鏈中元素的數目必等於其最小反鏈划分中反鏈的數目,由偏序集P按如下方式產生的圖G稱為偏序集的可比圖:G的節點集由P的元素組成,而e為G中的邊,僅當e的兩端點在P中是可比較的,有限全序集的可比圖為完全圖

This theorem says that the minimum number of non-decreasing sequences we need to cover the whole sequence equals the length of least decreasing subsequence.

通過分析可發現,

我們從字符串的末尾向左求最長不下降子序列,

用f[i] 代表 第i個位置在最長不下降子序列中的位置。

那么 總體就需要 $max(f[i],i\in[1,n]) $ 個顏色才能滿足要求。

第i個字符就染f[i] 色即可。

E1代碼:

int n;
char s[maxn];
int ans[maxn];
std::vector<char> v;
int isok = 1;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    scanf("%s", s + 1);
    ans[n] = 0;
    v.push_back(s[n]);
    for (int i = n - 1; i >= 1; --i)
    {
        int pos = lower_bound(ALL(v), s[i]) - v.begin();
        ans[i] = pos;
        if(pos==sz(v))
        {
            v.push_back(s[i]);
        }else
            v[pos] = s[i];
        if (pos > 1)
        {
            isok = 0;
        }
    }
    if (isok)
    {
        printf("YES\n");
        repd(i, 1, n)
        {
            printf("%d", ans[i]   );
        }
        printf("\n");
    } else
    {
        printf("NO\n");
    }
    return 0;
}

E2代碼:

int n;
char s[maxn];
int ans[maxn];
std::vector<char> v;
int isok = 1;
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    scanf("%s", s + 1);
    ans[n] = 1;
    v.push_back(s[n]);
    int ansnum = 1;
    for (int i = n - 1; i >= 1; --i)
    {
        int pos = lower_bound(ALL(v), s[i]) - v.begin();
        ans[i] = pos + 1;
        if (pos == sz(v))
        {
            v.push_back(s[i]);
        } else
            v[pos] = s[i];
        ansnum = max(ansnum, ans[i]);
    }


    printf("%d\n", ansnum);
    repd(i, 1, n)
    {
        printf("%d%c", ans[i], i == n ? '\n' : ' ' );
    }

    return 0;
}

F. Berland Beauty

思路:

首先把給定的m個限制按照降序排序,

然后降序的對於每一個限制\((ai,bi,gi)\),我們通過dfs 得出 數組\(fa[i]\) 代表 在ai到 bi 的有向路徑中 到達節點i的前繼節點。然后利用數組fa,更新ai到 bi 路徑中邊j的邊值 \(f_j = max(f_j, g_i)\) ,並用bj 標記下路徑中是否有邊j ,滿足 fj<gi 。如果沒有則答案是-1,最后如果各個限制沒有沖突,將那些沒有更新到的邊權設一個[1,1e6] 中的任意值。

代碼:

int n;
int id[maxn][maxn];
int fa[maxn];
struct node
{
    int f, t, w;
    bool operator < (const node &b) const
    {
        return w > b.w;
    }
} e[maxn];
int ans[maxn];
int m;
std::vector<int> son[maxn];
 
void dfs(int x, int pre)
{
    for (auto y : son[x])
    {
        if (y != pre)
        {
            fa[y] = x;
            dfs(y, x);
        }
    }
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    n = readint();
    repd(i, 2, n)
    {
        int x, y;
        x = readint();
        y = readint();
        son[x].push_back(y);
        son[y].push_back(x);
        id[x][y] = id[y][x] = i;
    }
    m = readint();
    repd(i, 1, m)
    {
        e[i].f = readint();
        e[i].t = readint();
        e[i].w = readint();
    }
    sort(e + 1, e + 1 + m);
    int flag = 1;
 
    repd(i, 1, m)
    {
        dfs(e[i].f, 0);
        int now = e[i].t;
        int bj = 0;
        do
        {
            int j = id[now][fa[now]];
            if (ans[j] <= e[i].w)
            {
                bj = 1;
                ans[j] = e[i].w;
            }
            now = fa[now];
        } while (now != e[i].f);
        if (!bj)
        {
            flag = 0;
            break;
        }
    }
    if (flag)
    {
        repd(i, 2, n)
        {
            printf("%d%c", max(ans[i], 1), i == n ? '\n' : ' ');
        }
    } else
    {
        printf("-1\n");
    }
    return 0;
}
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM