Description
还是树荫下,蕾姆抱着丝碧卡,向你提出若干个询问。
Input
Output
Sample Input
5
6 3
7 6 6 7 7 5
7 8 10
4 5
4 4 4 3
4 5 6 7 10
6 3
6 5 7 6 6 6
6 9 10
4 6
3 4 3 3
14 19 15 4 9 16
5 6
4 4 4 5 4
28 59 55 46 99 34
Sample Output
7 6 7 4 4 4 3 4 6 7 6 3 3 3 3 4 3 5 4 4 4 4 4
Data Constraint
Solution
先把a[ n ]算出来,(后面可能要用)若第 0 个为 n-1,第 n 个也为 n-1 ;否则第 n 个是 n。
如果把a分成长度为n+1的区间,则有:
比较第 i 个和第 i+1 个区间,可以发现以下规律:
- 每一个左边是 n 的 n-1 都向左移动了1步(和左边的那个数字交换位置,如果 n-1 下标为0,那么它会消失);
- 如果 n-1 左边是 n+1,那么它们两个就会变成n;
- 其它 n+1 和 n 都不变。
那么维护出 n-1 会和哪个 n+1 在什么时间相遇就好了。
如果把a分成长度为n的区间,可以发现不同的规律(令当前区间编号为 i ):
- 每一个 n+1 每次都会向右移动一步,如果它在区间 i 的末尾,它就会出现在 i+2 的开头,不会在 i+1 中出现;
- n+1 和 n-1 相遇会变成两个n;
- 其它 n-1 和 n 都不变。
由于这个 n+1 的消失实在鬼畜,我们不妨在每个区间末尾加上一个元素(初始为 n),那么第 x 个元素在一次变换后位置就是( x+1 ) mod ( n+1 )。
结合我比赛的做法,得到一种解法:
- 算出
(因为
后有可能会访问到
);
- 算出每一个 n+1 在什么时候会和哪一个 n-1 相遇,这个
扫一下就好了,相遇时间为
(令len为它们之间的长度,其实这个时间表示的是它们消失的那个区间的开头)。注意,这里要用单调栈维护;
- 给会和 n-1 相遇的 n+1 按相遇时间排序,给询问排序;
- 对于每一个询问x,先把会消失的n+1,n-1全部变成 n,然后考虑当前位置上的数是什么:
1). 若,说明它是 n-1(因为 n-1 是不动的,而且这个 n-1 还没有消失);
2). 若,说明它是 n+1 (因为每次a[ i ]位置上是2的下一次移动到了a[ i +n+1 ]的位置上);
3). 否则它就是 n 。
时间复杂度。
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof a)
#define N 100004
using namespace std;
ll x,l[N];
I T,n,m,a[N<<1],st[N],tp,cnt,ans[N];
struct node{ll x;I id;}q[N],p[N];
void R(){
x=0;I w=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
x*=w;
}
I cmp(node a,node b){return a.x<b.x;}
I main(){
freopen("way.in","r",stdin);
freopen("way.out","w",stdout);
R();T=x;
while(T--){
mem(a,cnt=tp=0),mem(l,255);
R(),n=x,R(),m=x;
F(i,0,n-1) R(),a[i]=x;a[n]=n-1+(a[0]>n-1);
F(i,1,m) R(),q[i]=node{x,i};
Fd(i,n-1,0){
if(a[i]==n-1) st[++tp]=i;
if(a[i]==n+1&&tp) l[i]=st[tp--];
}
Fd(i,n-1,0) if(l[i]==-1&&a[i]==n+1&&tp) l[i]=st[tp--];
F(i,0,n-1) if(l[i]!=-1){p[++cnt]=node{(l[i]>i?l[i]-i:l[i]-i+n+1)*n,i};}
sort(q+1,q+1+m,cmp);
sort(p+1,p+1+cnt,cmp);
I j=1;
F(i,1,m){
while(j<=cnt&&p[j].x<=q[i].x) a[p[j].id]=a[l[p[j].id]]=n,j++;
if(a[q[i].x%n]==n-1) ans[q[i].id]=n-1;
else ans[q[i].id]=n+(a[q[i].x%(n+1)]==n+1);
}
F(i,1,m) printf("%d ",ans[i]);
printf("\n");
}
return 0;
}