[CF1031E]Triple Flips
题目大意:给你一个长度为$n$的$01$串,一次操作定义为:选取$3$个等距的元素,使其$0$变$1$,$1$变$0$,要求在$\Big\lfloor \dfrac n 3\Big\rfloor+12$次操作内变为全$0$。输出是否可行以及方案
题解:skip1978的博客讲的十分详细。发现给的操作次数很少,基本上一次操作要使得$3$个元素变成$0$
对于区间$[l,r]$,若$a_l=0$,这一位不用翻转,缩小到区间$[l+1,r]$,这样$a_l,a_{l+1},a_{l+2}$有$4$中可能:
- $1,1,1:$翻转$a_l,a_{l+1},a_{l+2}$就可以使得这三位变$0$
- $1,0,1:$翻转$a_l,a_{l+2},a_{l+4}$就可以使得这三位变$0$
- $1,0,0:$翻转$a_l,a_{l+3},a_{l+6}$就可以使得这三位变$0$
- $1,1,0:$可以按相同方法收缩右端点,直到右端点也出现这样的情况
- 若$l,r$奇偶性相同,可以翻转$a_l,a_{\frac{l+r}{2}},a_r$和$a_{l+1},a_{\frac{l+r}{2}},a_{r-1}$使得这六位变成$0$
- 若$l,r$奇偶性不同,可以翻转$a_l,a_{\frac{l+r-1}{2}},a_{r-1}$和$a_{l+1},a_{\frac{l+r+1}{2}},a_r$使得这六位变成$0$
然后发现若区间长度大于等于$8$,一定可以翻转成$0$,并且所有合法的翻转只有$12$次,可以暴力枚举每一个操作是否使用即可
卡点:找到答案后忘记退出
C++ Code:
#include <cstdio>
#include <vector>
#define maxn 100010 int n, s[maxn];
struct Step {
int a, b, c;
inline Step() {}
inline Step(int __a, int __b, int __c) {a = __a, b = __b, c = __c;}
};
std::vector<Step> Ans;
bool find_ans = false; inline void reverse(int a, int b, int c) {
s[a] ^= 1, s[b] ^= 1, s[c] ^= 1;
Ans.push_back(Step(a, b, c));
}
inline void reverse(int a, int c) {
int b = a + c >> 1;
reverse(a, b, c);
} std::vector<std::pair<int, int> > V;
int tmp[maxn];
#define rev(x) tmp[x.first] ^= 1, tmp[x.first + x.second >> 1] ^= 1, tmp[x.second] ^= 1
inline bool end(int l, int r) {
for (int i = l; i <= r; i++) if (tmp[i]) return false;
return true;
}
void calc(int l, int r) {
for (int i = l; i <= r - 2; i++) {
for (int j = i + 2; j <= r; j += 2) {
V.push_back(std::make_pair(i, j));
}
}
int sz = V.size(), U = 1 << sz;
for (int i = 0; i < U; i++) {
for (int i = l; i <= r; i++) tmp[i] = s[i];
for (int j = 0; j < sz; j++) if (i & 1 << j) rev(V[j]);
if (end(l, r)) {
find_ans = true;
for (int j = 0; j < sz; j++) if (i & 1 << j) reverse(V[j].first, V[j].second);
return ;
}
}
} #define checkl(x, a, b, c) (s[x] == a && s[x + 1] == b && s[x + 2] == c)
#define work(l, r, L, R) {reverse(l, r), solve(L, R); return ;}
#define checkr(x, a, b, c) (s[x] == a && s[x - 1] == b && s[x - 2] == c)
void solve(int l, int r) {
if (r - l + 1 <= 8) {
while (r - l + 1 < 8 && l > 1) l--;
while (r - l + 1 < 8 && r < n) r++;
calc(l, r);
return ;
}
if (!s[l]) {solve(l + 1, r); return ;}
if (!s[r]) {solve(l, r - 1); return ;}
if (checkl(l, 1, 1, 1)) work(l, l + 2, l + 3, r);
if (checkl(l, 1, 0, 1)) work(l, l + 4, l + 3, r);
if (checkl(l, 1, 0, 0)) work(l, l + 6, l + 3, r);
if (checkr(r, 1, 1, 1)) work(r - 2, r, l, r - 3);
if (checkr(r, 1, 0, 1)) work(r - 4, r, l, r - 3);
if (checkr(r, 1, 0, 0)) work(r - 6, r, l, r - 3);
if (r - l & 1) {
reverse(l, r - 1), reverse(l + 1, r);
solve(l + 3, r - 3);
} else {
reverse(l, r), reverse(l + 1, r - 1);
solve(l + 3, r - 3);
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", s + i);
solve(1, n);
if (find_ans) {
puts("YES");
printf("%d\n", Ans.size());
for (std::vector<Step>::iterator it = Ans.begin(); it != Ans.end(); it++) {
printf("%d %d %d\n", it -> a, it -> b, it -> c);
}
} else puts("NO");
return 0;
}
[CF1031E]Triple Flips的更多相关文章
- Codeforces 1071 C - Triple Flips
C - Triple Flips 思路: 小范围暴力 大范围递归构造 构造方法: solve(l, r) 表示使l 到 r 区间全变为0的方法 为了使反转次数小于等于n/3 + 12 我们只需要保证每 ...
- Codeforces1071C Triple Flips 【构造】【Four Russians】
题目分析: 这种题目显然可以先考虑哪些无解.我们发现我们不考虑操作次数的时候,我们可以选择连续的三个进行异或操作. 这样我们总能使得一个序列转化为$000...000xy$的形式.换句话说,对于$00 ...
- Codeforces 1071C Triple Flips 构造
原文链接 https://www.cnblogs.com/zhouzhendong/p/CF1071C.html 题目传送门 - CF1071C 题意 给定一个长度为 n 的 01 数列,限定你在 $ ...
- Technocup 2019 - Elimination Round 2
http://codeforces.com/contest/1031 (如果感觉一道题对于自己是有难度的,不要后退,懂0%的时候敲一遍,边敲边想,懂30%的时候敲一遍,边敲边想,懂60%的时候敲一遍, ...
- Codeforces Round #517
传送门 A. Cram Time 你有一本书,阅读第\(i\)页需要花费\(i\)的时间.你第一天有\(a\)的时间,第二天有\(b\)的时间,问你的总阅读页数的最大值. Input: 一行包含\(2 ...
- 山东省第七届ACM省赛------Triple Nim
Triple Nim Time Limit: 2000MS Memory limit: 65536K 题目描述 Alice and Bob are always playing all kinds o ...
- hdu 3908 Triple(组合计数、容斥原理)
Triple Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 125536/65536 K (Java/Others) Total Su ...
- Flips测试类(page43)
测试用例:所用java类: StdOut,StdIn , Counter, StdRandom, public class Flips { public static void main(String ...
- hdu 5517 Triple(二维树状数组)
Triple Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
随机推荐
- 电子商城实录------定义init初始化的方法
路由方法的设置 //路由方法 private static function dispatch(){ //获取控制器名称(类比:英文单词的后缀) $controller_name=CONTROLLER ...
- 02---Nginx
Nginx .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: ...
- Python自动化运维——文件内容差异对比
Infi-chu: http://www.cnblogs.com/Infi-chu/ 模块:difflib 安装:Python版本大于等于2.3系统自带 功能:对比文本之间的差异,而且支持输出可读性比 ...
- 【转】谈谈 iOS 中图片的解压缩
转自:http://blog.leichunfeng.com/blog/2017/02/20/talking-about-the-decompression-of-the-image-in-ios/ ...
- Hadoop启动后无法启动NodeManager
在配置完Hadoop集群后,使用命令:“start-all.sh”进行启动集群.然后使用命令:“jps”查看进程启动情况,发现没有NodeManager 只需要使用命令:cd /usr/local/ ...
- android 怎么判断activity 从哪里启动的
有时候,你想要知道,有一个activity 从哪里启动的.怎么才能知道呢? 1.前提是,androidstadio 你下载了源码.找到你的activityBase的实现类,在startActivity ...
- stm8编程tips(stvd)
编译完成时显示程序占用的flash和ram大小 将附件压缩包中的mapinfo.exe解压到stvd的安装路径\stvd中 在工程上点右键选settings 右侧的选项卡选择Linker,将categ ...
- 多个excel合并(excel2007)
1.新建一个空的excel文件,在需要合并的目录下. 2.右键点击sheet1,点击查看代码 3.执行此段代码 Sub 合并当前目录下所有工作簿的全部工作表() Dim MyPath, MyName, ...
- React获取数据,假如为数组,使用map出现的问题
在平时做项目的时候,使用到了redux, 如果获取服务器端的数据,例如返回一个 data = [1,2,3,4]data.map(item => item*2) , 这样使用的话如果数据正常获 ...
- 03-Mysql数据库----安装与管理
本节掌握内容: mysql的安装.启动 mysql破解密码 统一字符编码 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流行的 ...