小球移动 | ||||||
|
||||||
Description | ||||||
给你n个小球,从左到右编号依次为1,2,3,4,5,6.........n,并规定小球1的左边的球号为n,小球n的右边的球号为1.现在有以下3种操作:A x y表示把编号为x小球移动到编号为y的小球的左边,B x y表示把编号为x小球移动到编号为y的小球的右边,Q 1 m为询问编号为m的小球右边的球号,Q 0 m为询问编号为m的小球左边的球号。 | ||||||
Input | ||||||
第一行有一个整数n(0<n<10000),表示有n组测试数据,随后每一组测试数据第一行是两个整数N,M,其中N表示球的个数(1<N<10000),M表示操作的的次数(0<M<10000)。
随后的M行,每行有三个数 s x y,s表示操作的类型,x,y为小球号。当s为Q时,若x为1,则询问小球y右边的球号,x为0,则询问小球y左边的球号。
|
||||||
Output | ||||||
输出每次询问的球号。 | ||||||
Sample Input | ||||||
1 6 3 A 1 4 B 3 5 Q 1 5 |
||||||
Sample Output | ||||||
3 |
炸一看题,这么多次询问 一定是线段树咯~。但是感觉链表也能实现,而且思路简单的多。但是我这个题看了一下提交状态,跑的最快的程序竟然只跑了1ms.看的我目瞪口呆,赶紧看了大牛的代码,刚开始理解还是比较难理解的,但是之后自己默默的推敲了一番,发现这种做法还是很奇妙的。
大牛永远都是大牛,小白只能仰望,然后膜拜。然后虚心学习,说不定真有一天就有小白这样崇拜你了呢~!!!!
这里废话不多说,题目是中文的 ,这里不进行题目大意的解释,直接讨论操作:
1.A操作.将a小球挪到b小球的左边:(A,1,4做为例子)
我们这里先举出实例:
序列长度为6的起始数组:
1 2 3 4 5 6.
这里我们再定义一个左右数组,用来存编号为i的小球的左,右分别为什么编号的小球:
比如对开始数组的初始化如下:
int xulie[10005]; int zuo[10005]; int you[10005]; for(int i=1;i<=n;i++)//这里n代表有n个小球~. { xulie[i]=i; } for(int i=1;i<=n;i++)//还是比较好理解的哈~~~~ { if(i==1) zuo[i]=xulie[n]; else zuo[i]=xulie[i-1]; } for(int i=1;i<=n;i++) { if(i==n) you[i]=xulie[1]; else you[i]=xulie[i+1]; }
挪动之后变成了:
2 3 1 4 5 6
这个时候我们先抛弃链表思维,直接观察变化:
1从原来的位子改变到了4的左边,这个时候.有以下变化量:
2左.
6左.
3右.
4左.
1左.
1右.
拿出第一个例子来说 ,原来2的左边是1 现在变成了6.
拿出第二个例子来说,原来6的左边是1现在变成了2.
拿出第三个例子来说,原来3的右边是4现在变成了1.
...
...
...
依次类推,我们得到了这样的一个变化关系.
这个时候我们先不要整理思路,因为我们现在只考虑了a操作。不急着写代码,我们这里再考虑b操作
2.B操作.将a小球挪到b小球的右边:(A,1,4做为例子)
原先的序列依旧是:
1 2 3 4 5 6
挪动之后是:
2 3 4 1 5 6
我们按照刚刚的思维,1从原来的位子改变到了4的右边,这个时候.有以下变化量:
2左.
6右.
5左.
4右.
1左.
1右.
这个时候我们整合思路:无论是1挪到4的左边还是右边,都有六个变化量,这个结论绝壁不是巧合,不信的小伙伴自行多列实例来观察变化.
这个时候我们有了结论,然后用代码模拟操作a就行了:
void caozuoa(int a,int b) { you[zuo[a]]=you[a];//6的右边变成2 zuo[you[a]]=zuo[a];//2的左边变成6 you[zuo[b]]=xulie[a];//依次类推. zuo[a]=zuo[b]; you[a]=xulie[b]; zuo[b]=xulie[a]; }
void caozuob(int a,int b) { you[zuo[a]]=you[a]; zuo[you[a]]=zuo[a]; zuo[you[b]]=xulie[a]; you[a]=you[b]; zuo[a]=xulie[b]; you[b]=xulie[a]; }
#include<stdio.h> #include<string.h> using namespace std; int xulie[10005]; int zuo[10005]; int you[10005]; void caozuoa(int a,int b) { you[zuo[a]]=you[a]; zuo[you[a]]=zuo[a]; you[zuo[b]]=xulie[a]; zuo[a]=zuo[b]; you[a]=xulie[b]; zuo[b]=xulie[a]; } void caozuob(int a,int b) { you[zuo[a]]=you[a]; zuo[you[a]]=zuo[a]; zuo[you[b]]=xulie[a]; you[a]=you[b]; zuo[a]=xulie[b]; you[b]=xulie[a]; } int main() { int t; scanf("%d",&t); while(t--) { int n,x; scanf("%d%d",&n,&x); getchar(); for(int i=1;i<=n;i++) { xulie[i]=i; } for(int i=1;i<=n;i++) { if(i==1) zuo[i]=xulie[n]; else zuo[i]=xulie[i-1]; } for(int i=1;i<=n;i++) { if(i==n) you[i]=xulie[1]; else you[i]=xulie[i+1]; } for(int j=0;j<x;j++) { char c; int a,b; scanf("%c %d %d",&c,&a,&b); getchar(); if(c=='A') { caozuoa(a,b); } if(c=='B') { caozuob(a,b); } if(c=='Q') { if(a==1) printf("%d\n",you[b]); else printf("%d\n",zuo[b]); } } } }