bzoj1493

1.请先仔细读题,一定注意hint...

总结:

1.一般先把算法相通并且有严格的证明。

2.实现的时候一定要把大体框架,关键部分想清楚。

3.如果实现的时候会犯错误的话一般是你前面做的一些操作影响了后面的操作而你并没有察觉

还有就是一定要注意边界。

然后说说这道题吧。。

1.一定注意只有一个点的时候!!

2.然后分清旋转与flip的区别

   1.  旋转的话是没有改变的结构的,也就是说如果顺时针是1 2 3 4 5 6 . 。。 。。。 那么旋转后你从1开始依旧是这样

       flip的话就会改变结构了。

  2.假如开始没有flip,然后你顺时针旋转就相当与每个位置-1,然后你flip。这和你先flip后旋转的结果是一样的,因为旋转只是让每个位置都要加或者都减,flip是不影响这种的改变的。

3.当flip=1即旋转了奇数次时,你旋转时就相当于所有位置+,偶数次是所有位置-

(注意我是以0 1 2 3 4 5 6 . 。 。 这样计数的因为这样的话flip会相当方便,然后你可以直接取模)

4.当寻找位置的时候 先如果flip等于1那么先让pos=-pos然后再开始加或减rotatee ,因为在原来位置你直接filp是最方便的(前面我已经说了旋转和flip谁先谁后是不影响的)所以我们直接在原来位置进行flip,然后再加或减旋转造成的影响。为什么原来位置最方便?因为0在中间啊。。如果你让除0以外的数在中间然后改变的话有要进行各种变换,然后就容易出错

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
struct nodee
{
	int rk, lk, num;
	bool issame;
};
nodee node[3000010];
int n, c;
int flip, rotatee;
void pushup(int k)
{
	node[k].rk = node[k << 1 | 1].rk;
	node[k].lk = node[k << 1].lk;
	node[k].num = node[k << 1].num + node[(k << 1) | 1].num - ((node[k << 1].rk == node[k << 1 | 1].lk) && node[k << 1].num&&node[k << 1 | 1].num);
}
void pushdown(int k)
{
	if (node[k].issame)
	{
		node[k << 1].rk = node[k << 1].lk =
			node[k << 1 | 1].rk = node[k << 1 | 1].lk =
			node[k].lk;
		node[k << 1].num = node[k << 1 | 1].num = 1;
		node[k << 1].issame = 1;
		node[k << 1 | 1].issame = 1;
		node[k].issame = 0;
	}
}
void build(int l, int r, int k)
{
	if (l == r)
	{
		scanf("%d", &node[k].rk);
		node[k].num = 1;
		node[k].lk = node[k].rk;
	}
	else
	{
		int mid = (l + r) >> 1;
		build(l, mid, k << 1);
		build(mid + 1, r, (k << 1) | 1);
		pushup(k);
	}
}
void same(int l, int r, int ll, int rr, int k, int color)
{
	if (ll >= l&&rr <= r)
	{
		node[k].issame = 1;
		node[k].lk = node[k].rk = color;
		node[k].num = 1;
		return;
	}
	else
	{
		int mid = (ll + rr) >> 1;
		pushdown(k);
		if (mid >= l)same(l, r, ll, mid, k << 1, color);
		if (mid + 1 <= r)same(l, r, mid + 1, rr, k << 1 | 1, color);
		pushup(k);
	}
}
int getnum(int l, int r, int ll, int rr, int k, int &colorr)
{
	if (ll >= l&&rr <= r)
	{
		colorr = node[k].lk;
		return node[k].num;
	}
	else
	{
		pushdown(k);
		int mid = (ll + rr) >> 1;
		int k1 = 0;
		int k2 = 0;
		if (mid >= l)k1 = getnum(l, r, ll, mid, k << 1, colorr);
		if (mid + 1 <= r)k2 = getnum(l, r, mid + 1, rr, k << 1 | 1, colorr);
		//pushup(k);
		return k1 + k2 - ((node[k << 1].rk == node[k << 1 | 1].lk) && k1 != 0 && k2 != 0);
	}
}
int flipp(int pos)
{
	if (flip)
		pos = -pos;
	pos += rotatee;
	pos %= n;
	return (pos%n + n) % n;
}
int getall()
{
	int ans = node[1].num;
	if (ans>1)
	ans -= (node[1].lk == node[1].rk);
	// printf("%d\n",ans);
	return ans;
}
int c1, c2;
int main()
{
	scanf("%d%d", &n, &c);
	build(0, n - 1, 1);
	int q;
	scanf("%d", &q);
	while (q--)
	{
		char str[10];
		scanf("%s", str);
		if (str[0] == 'R')
		{
			int k;
			scanf("%d", &k);
			if (flip)
				rotatee += k;
			else
				rotatee -= k;
		}
		if (str[0] == 'F')
		{
			flip ^= 1;
		}
		if (str[0] == 'S')
		{
			int i, j;
			scanf("%d%d", &i, &j);
			i--; j--;
			i = flipp(i);
			j = flipp(j);
			getnum(i, i, 0, n - 1, 1, c1);
			getnum(j, j, 0, n - 1, 1, c2);
			same(i, i, 0, n - 1, 1, c2);
			same(j, j, 0, n - 1, 1, c1);
		}
		if (str[0] == 'P')
		{
			int i, j, x;
			scanf("%d%d%d", &i, &j, &x);
			i--; j--;
			i = flipp(i);
			j = flipp(j);
			if (flip)
				swap(i, j);//这你flip后现在的顺时针就相当与原来的逆时针所以我们swap一下
				if (i>j)
				{
					same(i, n - 1, 0, n - 1, 1, x);
					same(0, j, 0, n - 1, 1, x);
				}
				if (i<=j)
					same(i, j, 0, n - 1, 1, x);
		}
		if (str[0] == 'C')
		{
			if (str[1] != 'S')
			{
				int ans = getall();
				printf("%d\n", ans);
			}
			else
			{
				int i, j;
				scanf("%d%d", &i, &j);
				i--; j--;
				i = flipp(i);
				j = flipp(j);
				int k1 = 0; int k2 = 0; int temp;
				if (flip)
					swap(i, j);//现在的顺时针询问相当于以前的逆时针询问所以我们只要换一下起点和终点就好了
					if (i>j)
					{
							k1 = getnum(i, n - 1, 0, n - 1, 1, temp);
							k2 = getnum(0, j, 0, n - 1, 1, temp);
							if (node[1].lk == node[1].rk)
								k1--;
					}
					if (i<=j)
					{
						k1 = getnum(i, j, 0, n - 1, 1, temp);
						//if (i == 0 && j == n - 1 && k1 > 1 && node[1].lk == node[1].rk)k1--;
					}
					printf("%d\n", k1 + k2);
			}
		}
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值