给定整数 n n n和两个 1 , ⋯ , n 1,\cdots ,n 1,⋯,n的排列 a , b a,b a,b
m m m个操作,操作有两种:
1 ≤ n , m ≤ 2 e 5 1 \le n,m \le 2e5 1≤n,m≤2e5
写了这场的 F F F和 G G G,一看 E E E是个数据结构,那也写一下 E E E吧。
其实这题转换一下非常好写的,因为修改操作只对 b b b数组修改,那么就对于 a a a的每一个位置,建立一个在数组 b b b中的权值线段树,映射过去就可以了。
e m m emm emm,然后在坚信自己的思路没问题的情况下,看了下题解,题解的做法挺多的,过几天在补,看了下题解给的主席树写法,增加了空间回收的思路,就去学了一下。
空间回收:树套树写法,复杂度在 l o g 2 n log^2n log2n左右,在每次都修改4次的情况下,基本需要 × 250 \times 250 ×250,但是考虑到一些点权值变为 0 0 0时,这个点就不需要了,所以可以将这个复杂度优化掉。
刚好卡过。
/*** keep hungry and calm CoolGuang! ***/
//#pragma GCC optimize(3)
#include
#define debug(x) cout<<#x<<":"<
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const int maxn = 2e5+7;
const int mod= 998244353;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;while(!isdigit(c)){
if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int a[maxn],b[maxn];
int pos[maxn],frc[maxn];
struct node{
int l,r;
int w;
}t[maxn*220];
vector<int>okNodes;
int cnt = n;
int newNode(){
int u;
if(okNodes.empty()){
u=++cnt; return u;}
u = okNodes.back();
okNodes.pop_back();
return u;
}
void insert(int &x,int l,int r,int pos,int w){
if(!x) x = newNode();
t[x].w += w;
if(l == r) return;
int mid = (l+r)/2;
if(pos<=mid) insert(t[x].l,l,mid,pos,w);
else insert(t[x].r,mid+1,r,pos,w);
if(!t[x].w){
okNodes.push_back(x);
t[x].l = t[x].r = 0;
x = 0;
}
}
ll query(int now,int l,int r,int x,int y){
if(!now) return 0;
if(x<=l && y>=r) return t[now].w;
ll ans = 0;
int mid = (l+r)/2;
if(x<=mid) ans += query(t[now].l,l,mid,x,y);
if(y>mid) ans += query(t[now].r,mid+1,r,x,y);
return ans;
}
void update(int pos,int x,int w){
while(pos<=n) insert(pos,1,n,x,w),pos += pos&-pos;}
ll getsum(int pos,int x,int y){
ll ans = 0;
while(pos){
ans += query(pos,1,n,x,y);
pos -= pos&-pos;
}return ans;
}
int main(){
read(n);read(m);
cnt = n;
for(int i=1;i<=n;i++){
read(a[i]);
frc[a[i]] = i;
}
for(int i=1;i<=n;i++){
read(b[i]);
pos[b[i]] = i;
}
for(int i=1;i<=n;i++) update(i,pos[a[i]],1);
for(int i=1;i<=m;i++){
int op,l1,r1,l2,r2;
read(op);read(l1);read(r1);
if(op == 1){
read(l2);read(r2);
dl(getsum(r1,l2,r2)-getsum(l1-1,l2,r2));
}else{
int tmpx = frc[b[l1]],tmpy = frc[b[r1]];
update(tmpx,l1,-1);
update(tmpy,r1,-1);
update(tmpx,r1,1);
update(tmpy,l1,1);
swap(b[l1],b[r1]);
}
}
return 0;
}
/**
2 2
-1 -2
4 5
**/