博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CF1031E]Triple Flips
阅读量:5091 次
发布时间:2019-06-13

本文共 3081 字,大约阅读时间需要 10 分钟。

题目大意:给你一个长度为$n$的$01$串,一次操作定义为:选取$3$个等距的元素,使其$0$变$1$,$1$变$0$,要求在$\Big\lfloor \dfrac n 3\Big\rfloor+12$次操作内变为全$0$。输出是否可行以及方案

题解:讲的十分详细。发现给的操作次数很少,基本上一次操作要使得$3$个元素变成$0$

对于区间$[l,r]$,若$a_l=0$,这一位不用翻转,缩小到区间$[l+1,r]$,这样$a_l,a_{l+1},a_{l+2}$有$4$中可能:

  1. $1,1,1:$翻转$a_l,a_{l+1},a_{l+2}$就可以使得这三位变$0$
  2. $1,0,1:$翻转$a_l,a_{l+2},a_{l+4}$就可以使得这三位变$0$
  3. $1,0,0:$翻转$a_l,a_{l+3},a_{l+6}$就可以使得这三位变$0$
  4. $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 
#include
#define maxn 100010int 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
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
> V;int tmp[maxn];#define rev(x) tmp[x.first] ^= 1, tmp[x.first + x.second >> 1] ^= 1, tmp[x.second] ^= 1inline 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
::iterator it = Ans.begin(); it != Ans.end(); it++) { printf("%d %d %d\n", it -> a, it -> b, it -> c); } } else puts("NO"); return 0;}

  

转载于:https://www.cnblogs.com/Memory-of-winter/p/9925338.html

你可能感兴趣的文章
获取地址栏参数
查看>>
Yale CAS + .net Client 实现 SSO 的完整版
查看>>
java之hibernate之helloworld
查看>>
微服务之初了解(一)
查看>>
Iterator invalidation(迭代器失效)
查看>>
GDOI DAY1游记
查看>>
中介者模式
查看>>
认识 web 服务器端脚本语言 PHP
查看>>
RHEL 无图形界面安装oracle 11gr2
查看>>
sql连接left join、right join、inner join的使用
查看>>
h5 的localStorage和sessionStorage存到缓存里面的值是string类型
查看>>
自定义序列化
查看>>
1020. 分解质因数
查看>>
1099.后缀子串排序
查看>>
阿里云Linux服务器环境部署总结-安装web环境PHP
查看>>
P4211 [LNOI2014]LCA LCT
查看>>
(面试题)类的初始化顺序
查看>>
数据库系统概念-查询处理
查看>>
配置C8051F020模板工程
查看>>
weblogic12.1.3部署应用程序
查看>>