CF1876D Lexichromatography
CF1876D Lexichromatography
题目描述
给定一个长为
- 每个位置恰好染上其中一种颜色。
- 对于所有的值
,在这个序列的任意子区间 中,值为 且为红色的位置数 减去 值为 且为蓝色的位置数 的绝对值不超过 1。 - 如果按照位置顺序将所有红色的数排成序列
,蓝色的数排成序列 ,那么 的字典序必须 严格大于 的字典序。
统计所有的合法染色方案数。对 998244353 取模。
Solution
不妨先看看每个条件等价于什么。对于条件
考虑计数两个序列字典序相同的情况。显然如果有一个颜色出现次数为奇数就是不存在字典序相同的情况。否则考虑每种权值,将
时间复杂度
Code
int N, A[_N], maxn = 0, fa[_N], pw[_N];
int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
vector<int> pos[_N];
vector<pii> vec;
signed main() {
cin.tie(0)->sync_with_stdio(0);
cin >> N; pw[0] = 1;
For(i, 1, N) {
pw[i] = pw[i-1] * 2ll % mod;
cin >> A[i];
pos[A[i]].emplace_back(i);
Max(maxn, A[i]);
}
bool flag = 0;
int ans = 0;
For(i, 1, maxn) if (!pos[i].empty()) {
++ans;
flag |= pos[i].size() & 1;
for (size_t j = 0; j < pos[i].size(); j += 2)
vec.emplace_back(pos[i][j], pos[i][j+1]);
}
sort(vec.begin(), vec.end());
for (size_t i = 1; i < vec.size(); ++i)
if (vec[i].second < vec[i-1].second)
flag = 1;
if (flag) return cout << pw[ans-1] % mod << '\n', 0;
int cnt = ans;
iota(fa + 1, fa + maxn + 1, 1);
for (size_t i = 1; i < vec.size(); ++i)
if (vec[i].first < vec[i-1].second) {
int fx = find(A[vec[i].first]), fy = find(A[vec[i-1].second]);
if (fx == fy) continue;
fa[fx] = fy, --cnt;
}
cout << (pw[ans-1] - pw[cnt-1] + mod) % mod << '\n';
}
分类:
标签:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步