B. RGB Caps

\(n\) 个学生排成一排,每个人戴着红、绿、蓝三种不同的帽子。从队列的开头开始分别给这些学生编号为 \(1, 2, 3, \cdots, n\)

给你 \(k\) 条证词。第 \(i\) 条证词如下:

  • 从第 \(1\) 个人到第 \(p_i\) 个人中戴的帽子中出现最多的颜色之一是 \(c_i\)

其中 \(c_i\) 表示 RGB,分别表示红、绿和蓝。当 \(i \neq j\) 时,\(p_i \neq p_j\)

要求构造一种合法的戴帽子方式。若有证词存在矛盾则输出 -1

限制:

  • \(1 \leqslant k \leqslant n \leqslant 10^5\)
  • \(1 \leqslant p_i \leqslant n\)

算法分析

由于“当 \(i \neq j\) 时,\(p_i \neq p_j\) ”,所以不需要考虑矛盾的情况
可以考虑像 RGBRGB... 这样均匀地分配

具体地,我们可以将 \(s\) 初始化成 \(n\)R 拼接起来的字符串,然后将 \(s\) 的第 \(p\) 个字符更改为 \(c\)

接下来我们遍历 \(s\) 的每个字符:

  • \(i\%3 = 1\) 时,\(s_i\) 保持不变
  • \(i\%3 = 2\) 时,若此时还满足 \(s_i = s_{i-1}\),如果 \(s_{i-1}=\) R,则将 \(s_i\) 更改成 G;若 \(s_{i-1}\neq\) R,则将 \(s_i\) 更改成 R
  • \(i\%3 = 0\) 时,将 \(s_i\) 更改成和 \(s_{i-1}\)\(s_{i-2}\) 都不同的颜色即可
代码实现
#include <bits/extc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)

using std::cin;
using std::cout;
using std::string;

int main() {
    int n, k;
    cin >> n >> k;
    
    string s(n, 'R');
    rep(i, k) {
        int p; char c;
        cin >> p >> c;
        --p;
        s[p] = c;
    }
    
    rep(i, n) {
        if (i%3 == 1) {
            if (s[i] == s[i-1]) {
                if (s[i-1] == 'R') s[i] = 'G';
                else s[i] = 'R';
            }
        }
        if (i%3 == 2) {
            s[i] = 'R' ^ 'G' ^ 'B' ^ s[i-1] ^ s[i-2];
        }
    }
    
    cout << s << '\n'; 
    
    return 0;
}