版权声明:希望大家转载的时候把公式转载好一点QAQ,我就公式打得很辛苦了... https://blog.csdn.net/Myriad_Dreamin/article/details/85035454
求区间
中
的数字出现了多少个。
因为
均是排列,所以区间数字分布具有可加性。
所以分块+树状数组,时间复杂度约为
.
因为常数较大,所以
不一定能过,通过卡
两侧枚举的时间可过。
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <cctype>
#include <cstring>
#define lowbit(_x) ((_x)&-(_x))
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char GET_CHAR(){
if(head==tail){
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
if(head==tail)return EOF;
}
return *head++;
}
inline int READ(){
int x=0,f=1;char c=GET_CHAR();
for(;!isdigit(c);c=GET_CHAR()){
if(c==EOF)return EOF;
if(c=='-')f=-1;
}
for(;isdigit(c);c=GET_CHAR())x=(((x<<2)+x)<<1)+c-'0';
return x*f;
}
const int N=200505,sqrtN=650;
int ref[N+5],bit[405][N+5];
int A[N+5],B[N+5],ra[N+5],rb[N+5],n;
void add(int *bit,int x,int v){
while(x<=n){
bit[x]+=v;
x+=lowbit(x);
}
return ;
}
int sum(int *bit,int x){
int res=0;
while(x>0){
res+=bit[x];
x-=lowbit(x);
}
return res;
}
int Sum(int *bit,int l,int r){
return sum(bit,r)-sum(bit,l-1);
}
int main(){
n=READ();
int m=READ();
for(int i=sqrtN;i<=n;i++){
ref[i]=ref[i-sqrtN]+1;
}
for(int i=1;i<=n;i++){
A[i]=READ();
ra[A[i]]=i;
}
for(int i=1;i<=n;i++){
B[i]=READ();
rb[B[i]]=i;
add(bit[ref[ra[B[i]]]],i,1);
}
while(m--){
int o=READ();
if(o==1){
int a,b,c,d;
a=READ();b=READ();c=READ();d=READ();
int t=ref[a]+1;
int res=0;
while(ref[a]<t&&a<=b){
if(c<=rb[A[a]]&&rb[A[a]]<=d)res++;
a++;
}
t=ref[b];
while(ref[a]<t&&a<=b){
res+=Sum(bit[ref[a]],c,d);
a+=sqrtN;
}
while(a<=b){
if(c<=rb[A[a]]&&rb[A[a]]<=d)res++;
a++;
}
printf("%d\n",res);
}
else{
int a,b;
a=READ();b=READ();
add(bit[ref[ra[B[a]]]],a,-1);
add(bit[ref[ra[B[b]]]],b,-1);
add(bit[ref[ra[B[a]]]],b,1);
add(bit[ref[ra[B[b]]]],a,1);
swap(B[a],B[b]);
swap(rb[B[a]],rb[B[b]]);
}
}
//system("pause");
}