题目:CF 323 C.
题目大意:给定两个长度为
n
n
n的排列
a
,
b
a,b
a,b,每次询问有多少个数
a
[
l
1..
r
1
]
a[l1..r1]
a[l1..r1]和
b
[
l
2..
r
2
]
b[l2..r2]
b[l2..r2]中同时出现.
设询问次数为
n
n
n,则
1
≤
n
≤
1
0
6
,
1
≤
m
≤
2
∗
1
0
5
1\leq n\leq 10^6,1\leq m\leq 2*10^5
1≤n≤106,1≤m≤2∗105.
首先很显然我们要把 b b b中每一个数在 a a a中的出现位置记录下来.
考虑一个简化的问题,若 l 2 = 1 , r 2 = n l2=1,r2=n l2=1,r2=n,那么我们现在开一个数组 c n t [ i ] cnt[i] cnt[i]表示 a [ i ] a[i] a[i]的出现数量,那么答案即为 ∑ i = l 1 r 1 c n t [ i ] \sum_{i=l1}^{r1}cnt[i] ∑i=l1r1cnt[i],建立线段树维护即可(我知道这个值一定是 r 1 − l 1 + 1 r1-l1+1 r1−l1+1,但是我们要对下面的解法有所提示).
若有了 b b b的区间限制,那么考虑把维护 c n t cnt cnt数组的线段树换成主席树,第 i i i棵主席树维护 l 2 = 1 , r 2 = i l2=1,r2=i l2=1,r2=i时的 c n t cnt cnt数组.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=1000000,C=24;
int ri(){
int x=0;
char c=getchar();
for (;c<'0'||c>'9';c=getchar());
for (;c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
return x;
}
int n,b[N+9],ord[N+9];
struct tree{
int l,r,sum,ls,rs;
}tr[N*C+9];
int rot[N+9],cn,ans;
void Pushup(int k){tr[k].sum=tr[tr[k].ls].sum+tr[tr[k].rs].sum;}
int Build(int L,int R){
int now=++cn;
tr[now].l=L;tr[now].r=R;
if (L==R) return now;
int mid=L+R>>1;
tr[now].ls=Build(L,mid);tr[now].rs=Build(mid+1,R);
return now;
}
int Add_tree(int k,int x){
int now=++cn;tr[now]=tr[k];
if (tr[k].l==tr[k].r){++tr[now].sum;return now;}
int mid=tr[k].l+tr[k].r>>1;
if (x<=mid) tr[now].ls=Add_tree(tr[k].ls,x);
else tr[now].rs=Add_tree(tr[k].rs,x);
Pushup(now);
return now;
}
int Query(int L,int R,int k){
if (L==tr[k].l&&R==tr[k].r) return tr[k].sum;
int mid=tr[k].l+tr[k].r>>1;
if (R<=mid) return Query(L,R,tr[k].ls);
else if (L>mid) return Query(L,R,tr[k].rs);
else return Query(L,mid,tr[k].ls)+Query(mid+1,R,tr[k].rs);
}
int f(int x){return (x-1+ans)%n+1;}
Abigail into(){
n=ri();
for (int i=1;i<=n;++i)
ord[ri()]=i;
for (int i=1;i<=n;++i)
b[i]=ord[ri()];
}
Abigail work(){
rot[0]=Build(1,n);
for (int i=1;i<=n;++i)
rot[i]=Add_tree(rot[i-1],b[i]);
}
Abigail getans(){
int m,l1,r1,l2,r2;
m=ri();
for (int i=1;i<=m;++i){
l1=f(ri());r1=f(ri());l2=f(ri());r2=f(ri());
if (l1>r1) swap(l1,r1);if (l2>r2) swap(l2,r2);
printf("%d\n",ans=Query(l1,r1,rot[r2])-Query(l1,r1,rot[l2-1]));++ans;
}
}
int main(){
into();
work();
getans();
return 0;
}