P9741 翻转与反转

P9741 翻转与反转

「KDOI-06-J」翻转与反转

题目描述

小 W 有一个长度为 n n n 01 01 01 序列 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an,他将对这个序列按顺序进行 n n n 次操作。

在第 i i i 次操作中( 1 ≤ i ≤ n 1\le i\le n 1in),小 W 将按顺序执行以下两种变换:

  1. 将区间 [ 1 , i ] [1,i] [1,i] 中的数按下标翻转。形式化地说,在这次变换之后,序列 a a a 将变为 a i , a i − 1 , … , a 1 , a i + 1 , a i + 2 , … , a n a_i,a_{i-1},\ldots,a_{1},a_{i+1},a_{i+2},\ldots,a_n ai,ai1,,a1,ai+1,ai+2,,an
  2. 将区间 [ 1 , i ] [1,i] [1,i] 中的数按值翻转。形式化地说,在这次变换之后,对于任意 1 ≤ j ≤ i 1\le j\le i 1ji,若 a j = 0 a_j=0 aj=0,则 a j a_j aj 将变为 1 1 1,否则 a j a_j aj 将变为 0 0 0

小 W 想要知道,在全部 n n n 次操作结束后,序列 a a a 中每个元素的值。

输入格式

从标准输入读入数据。

输入的第一行包含一个正整数 n n n,表示序列长度。

接下来一行 n n n 个整数,表示序列 a 1 , a 2 , … , a n a_1,a_2,\ldots, a_n a1,a2,,an。保证 a i = 0 a_i=0 ai=0 1 1 1

输出格式

输出到标准输出。

输出包含一行 n n n 个整数,表示操作结束后序列 a a a 中每个元素的值。

样例 #1

样例输入 #1

3
1 1 1

样例输出 #1

0 0 1

样例 #2

样例输入 #2

8
1 0 1 1 1 0 0 1

样例输出 #2

0 1 0 1 1 1 1 0

提示

【样例解释 #1】

序列 a a a 的变化如下表所示:

操作次数序列 a a a 的变化
1 1 1 [ 1 , 1 , 1 ] → [ 1 , 1 , 1 ] → [ 0 , 1 , 1 ] [1,1,1]\to [1,1,1]\to[0,1,1] [1,1,1][1,1,1][0,1,1]
2 2 2 [ 0 , 1 , 1 ] → [ 1 , 0 , 1 ] → [ 0 , 1 , 1 ] [0,1,1]\to [1,0,1]\to[0,1,1] [0,1,1][1,0,1][0,1,1]
3 3 3 [ 0 , 1 , 1 ] → [ 1 , 1 , 0 ] → [ 0 , 0 , 1 ] [0,1,1]\to [1,1,0]\to[0,0,1] [0,1,1][1,1,0][0,0,1]

【样例解释 #2】

序列 a a a 的变化如下表所示:

操作次数操作后的序列 a a a
- [ 1 , 0 , 1 , 1 , 1 , 0 , 0 , 1 ] [1,0,1,1,1,0,0,1] [1,0,1,1,1,0,0,1]
1 1 1 [ 0 , 0 , 1 , 1 , 1 , 0 , 0 , 1 ] [0,0,1,1,1,0,0,1] [0,0,1,1,1,0,0,1]
2 2 2 [ 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 ] [1,1,1,1,1,0,0,1] [1,1,1,1,1,0,0,1]
3 3 3 [ 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1 ] [0,0,0,1,1,0,0,1] [0,0,0,1,1,0,0,1]
4 4 4 [ 0 , 1 , 1 , 1 , 1 , 0 , 0 , 1 ] [0,1,1,1,1,0,0,1] [0,1,1,1,1,0,0,1]
5 5 5 [ 0 , 0 , 0 , 0 , 1 , 0 , 0 , 1 ] [0,0,0,0,1,0,0,1] [0,0,0,0,1,0,0,1]
6 6 6 [ 1 , 0 , 1 , 1 , 1 , 1 , 0 , 1 ] [1,0,1,1,1,1,0,1] [1,0,1,1,1,1,0,1]
7 7 7 [ 1 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ] [1,0,0,0,0,1,0,1] [1,0,0,0,0,1,0,1]
8 8 8 [ 0 , 1 , 0 , 1 , 1 , 1 , 1 , 0 ] [0,1,0,1,1,1,1,0] [0,1,0,1,1,1,1,0]

【样例 #3】

见选手文件中的 revflip/revflip3.inrevflip/revflip3.ans

【样例 #4】

见选手文件中的 revflip/revflip4.inrevflip/revflip4.ans

【数据范围】

对于所有数据保证: 1 ≤ n ≤ 2 × 1 0 6 1\le n\le 2\times 10^6 1n2×106,且对于任意 1 ≤ i ≤ n 1\le i\le n 1in a i = 0 a_i=0 ai=0 1 1 1

测试点编号 n ≤ n\le n特殊性质
1 ∼ 3 1\sim 3 13 1 0 3 10^3 103
4 ∼ 5 4\sim 5 45 1 0 5 10^5 105
6 ∼ 7 6 \sim 7 67 2 × 1 0 6 2\times 10^6 2×106 a i = 0 a_i=0 ai=0
8 ∼ 10 8\sim 10 810 2 × 1 0 6 2\times 10^6 2×106

思路

起初是暴力写的,过不了全部测试。看了题解,也听到很多关于奇偶…,很不理解。别人的代码,看不下去,也看不懂,只是看看思路,朝那个方向,去思考,发现规律。最后算是解决了。

我们先思考第一个变换
假设

起初: 1 2 3 4 …i…n
变换一次: i…4 3 2 1…n
变换两次: i+1 1 2 3 4…i…n

可以发现对于1~i,进行了两次翻转,位置向后移一.怎样理解呢,如果翻转的数据不变,翻转两次相当于,回到原位不变,而按照题中的翻转,第一次是1 ~ i;第二次多了一个i+1,转到了第一位,以至于翻转两次,向后移一。

`当进行n次偏转后, 翻转偶数次k的,向后移k/2;
翻转奇数次k+1的,第k+1也就是i=n,所有数字的翻转。
因此再定义一个数组b,将元素按新位置存放

再看第二次变换,

易知反转偶数次不变,a[n]反转1次,也就是n-=2,所对应下标都是反转奇数次,要改变。所以,在第一个变换之前,现将所有该反转的数字,改变,这样之后不用考虑第二种变化

代码如下

#include<bits/stdc++.h>
using namespace std;
int n,a[2000006],b[2000006];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	//重点要先进行第二种变换
	for(int j=n;j>=1;j-=2)
	// j-=2,都是转奇数次,需改变。
	{
		if(a[j]==1)	a[j]=0; 
	    else     a[j]=1; 
	}
//下面是第一种变换
	for(int j=1;j<=n;j++)  
	{
		if((n-j+1)&1) //a[j]移动次数是否为奇数 
		b[n-((n-j+1)/2+j)+1]=a[j];
		else
		b[(n-j+1)/2+j]=a[j];
	}
	for(int i=1;i<=n;i++)
	cout<<b[i]<<" ";
}


  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值