大家好, 我非常喜欢暴力数据结构, 于是就用分块A了此题
分块题,考虑前缀和 \(b_i\) 表示 bitset 即 \(0\) ~ $i
$ 出现过的数字,然后考虑直接暴力复制块然后前缀和,修改也很简单,直接删除完了 swap 一下,再弄回去
时间复杂度 \(O(q \sqrt n + q \frac{n}{w})\)
// by Isaunoya
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include
#include
using namespace std;
#define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
#define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
//#define int long long
const int _ = 1 << 21;
struct I {
char fin[_], *p1 = fin, *p2 = fin;
inline char gc() {
return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
}
inline I& operator>>(int& x) {
bool sign = 1;
char c = 0;
while (c < 48) ((c = gc()) == 45) && (sign = 0);
x = (c & 15);
while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
x = sign ? x : -x;
return *this;
}
inline I& operator>>(double& x) {
bool sign = 1;
char c = 0;
while (c < 48) ((c = gc()) == 45) && (sign = 0);
x = (c - 48);
while ((c = gc()) > 47) x = x * 10 + (c - 48);
if (c == '.') {
double d = 1.0;
while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
}
x = sign ? x : -x;
return *this;
}
inline I& operator>>(char& x) {
do
x = gc();
while (isspace(x));
return *this;
}
inline I& operator>>(string& s) {
s = "";
char c = gc();
while (isspace(c)) c = gc();
while (!isspace(c) && c != EOF) s += c, c = gc();
return *this;
}
} in;
struct O {
char st[100], fout[_];
signed stk = 0, top = 0;
inline void flush() {
fwrite(fout, 1, top, stdout), fflush(stdout), top = 0;
}
inline O& operator<<(int x) {
if (top > (1 << 20)) flush();
if (x < 0) fout[top++] = 45, x = -x;
do
st[++stk] = x % 10 ^ 48, x /= 10;
while (x);
while (stk) fout[top++] = st[stk--];
return *this;
}
inline O& operator<<(char x) {
fout[top++] = x;
return *this;
}
inline O& operator<<(string s) {
if (top > (1 << 20)) flush();
for (char x : s) fout[top++] = x;
return *this;
}
} out;
#define pb emplace_back
#define fir first
#define sec second
template < class T > inline void cmax(T & x , const T & y) {
(x < y) && (x = y) ;
}
template < class T > inline void cmin(T & x , const T & y) {
(x > y) && (x = y) ;
}
int n , m ;
const int maxn = 2e5 + 200 ;
template < int bl >
struct BLOCK {
bitset < maxn > b[maxn / bl] ;
bitset < maxn > temp ;
int per[maxn] ;
inline void ins(int x , int v) {
per[x] = v ;
for(register int i = x ; i <= n ; i += bl)
b[i / bl].set(v) ;
}
inline void del(int x , int v) {
for(register int i = x ; i <= n ; i += bl)
b[i / bl].reset(v) ;
}
inline bitset < maxn > qry(int x) {
temp = x / bl ? b[x / bl - 1] : 0 ;
rep(i , max(x / bl * bl , 1) , x)
temp.set(per[i]) ;
return temp ;
}
inline bitset < maxn > qry(int l , int r) {
return qry(r) ^ qry(l - 1) ;
}
};
int a[maxn] , b[maxn] ;
BLOCK < 256 > A ;
BLOCK < 512 > B ;
signed main() {
#ifdef _WIN64
freopen("testdata.in" , "r" , stdin) ;
#endif
in >> n >> m ;
rep(i , 1 , n) in >> a[i] , A.ins(i , a[i]) ;
rep(i , 1 , n) in >> b[i] , B.ins(i , b[i]) ;
while(m --) {
int opt ;
in >> opt ;
if(opt == 1) {
int l , r , a , b ;
in >> l >> r >> a >> b ;
int ans = (A.qry(l , r) & B.qry(a , b)).count() ;
out << ans << '\n' ;
}
else {
int x , y ;
in >> x >> y ;
B.del(x , b[x]) ; B.del(y , b[y]) ;
swap(b[x] , b[y]) ;
B.ins(x , b[x]) ; B.ins(y , b[y]) ;
}
}
return out.flush(), 0;
}