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;
}