ABC 155 F Perils in Parallel
这个题可以抽象成一个串和若干个操作,每个操作能翻转串的子串,问这些操作能否把串翻转成全0
首先想到暴力思路,操作M能让串处于 S 1 S_1 S1和 S 2 S_2 S2两种状态,问题就划分为操作 1 , 2 , . . . , M − 1 1,2,...,M-1 1,2,...,M−1 是否能将 S 1 S_1 S1或者 S 2 S_2 S2的串翻转成全0,继续划分,分支总数为 2 M 2^M 2M,时间复杂度到达指数级肯定是不行的。
接着想想dp方法, d p [ M ] [ ? ] dp[M][?] dp[M][?]涉及到M个操作, ? ? ?取什么样的属性呢?想想 d p [ M ] [ ? ] dp[M][?] dp[M][?]从 d p [ M − 1 ] [ ? ] dp[M-1][?] dp[M−1][?]中怎么提取信息? 用排除法的话,?不能是串的状态,因为串太长所以不能表示状态,?为空 dp[M]能得到的信息大概是dp[M-1]为true的时候 dp[M]为true,而dp[M-1]不为true的时候,dp[M]能否为true不能判断,感觉dp不行啊
接着想想贪心的方法,M个操作里面有偏序关系存在吗?要说操作之间的区别那就是操作之前存在影响位数大小的差别,差别不能决定偏序关系,而且M个操作不一定都要选,即使有偏序关系也选不了,所以感觉贪心走不远
两大神器都没用,想想是不是有什么特殊的性质,如果一个操作只能翻一个位,那么这个位肯定最后能翻成0,这一位相当没有,如果两个操作翻的位没有交集,那么可以divide and conquer,如果有交集感觉不是很好处理
想到这里,觉得没什么思路,找答案,找到第一名noshi91的答案
#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <set>
#include <utility>
#include <vector>
int main() {
using P = std::pair<int, int>;
int n, m;
std::cin >> n >> m;
/*
問題を言い換えるための下処理をする
*/
std::vector<int> a(n), c(n + 1, 0); // c: 隣接する b の差分
std::vector<P> bombs(n); // first: A, second: B
for (P &e : bombs) {
std::cin >> e.first >> e.second;
}
std::sort(bombs.begin(), bombs.end()); // 座標の昇順にする
for (int<