题目链接
一道神秘思维题。
不难发现本题的 1 操作等价于两个子串都尽可能进行何意味操作后,剩下的串是否相当。(这也是我思维的截至点)。
因此变成相邻消除,很难维护。考虑异或,但是不难发现异或具有交换律,因此不可行。
考虑改变思路,现在我们需要开发出一种运算,满足其具有结合律,不具有交换律。联想到了矩阵乘法。
考虑 \(2\times2\) 的矩阵
\[\begin{pmatrix}
a,b\\
c,d
\end{pmatrix}
\]
对于相同的矩阵,显然有
\[\begin{pmatrix}
a,b\\
c,d
\end{pmatrix}
\times
\begin{pmatrix}
a,b\\
c,d
\end{pmatrix}
=
\begin{pmatrix}
1,0\\
0,1
\end{pmatrix}
\]
后者,就相当于矩阵里面的 1 。
因此有
\[\left\{
\begin{align}
a^2+bc=1\qquad\\
ab+bd=0\qquad\\
ac+cd=0\qquad\\
bc+d^2=1\qquad
\end{align}
\right.
\]
胡乱构造一下,得到矩阵可以变成:
\[\begin{pmatrix}
a,1-a\\
1+a,-a
\end{pmatrix}
\]
接下来用线段树维护矩阵就好了。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const unsigned int mod = 1e9 + 7;
const int N = 5e5 + 10;
struct matrix{unsigned int a[2][2];matrix(){a[0][0] = a[0][1] = a[1][0] = a[1][1] = 0;} void new_mat(unsigned x){a[0][0] = x;a[0][1] = 1 - x;a[1][0] = 1 + x;a[1][1] = -x;return ;}matrix operator * (const matrix &oth) const{matrix c;c.a[0][0] = a[0][0] * oth.a[0][0] + a[0][1] * oth.a[1][0];c.a[0][1] = a[0][0] * oth.a[0][1] + a[0][1] * oth.a[1][1];c.a[1][0] = a[1][0] * oth.a[0][0] + a[1][1] * oth.a[1][0];c.a[1][1] = a[1][0] * oth.a[0][1] + a[1][1]* oth.a[1][1];return c;}bool operator == (const matrix &oth) const{if(a[0][0] != oth.a[0][0]) return 0;if(a[0][1] != oth.a[0][1]) return 0;if(a[1][0] != oth.a[1][0]) return 0;if(a[1][1] != oth.a[1][1]) return 0;return 1;}
};
struct seg{matrix tre[N << 2];#define ls (p*2)#define rs (p*2+1)unsigned int a[N];void pushup(int p){tre[p] = tre[ls] * tre[rs];return ;}void build(int pl,int pr,int p){if(pl == pr){tre[p].new_mat(a[pl]);return ;}int mid = pl + pr >> 1;build(pl,mid,ls);build(mid+1,pr,rs);pushup(p);}void update(int x,int pl,int pr,int p,int k){if(pl == pr){tre[p].new_mat(k);return;}int mid = pl + pr >> 1;if(x <= mid) update(x,pl,mid,ls,k);else update(x,mid+1,pr,rs,k);pushup(p);return ;}matrix query(int L,int R,int pl,int pr,int p){if(L <= pl && pr <= R){return tre[p];}int mid = pl + pr >> 1;if(L <= mid && mid < R)return query(L,R,pl,mid,ls) * query(L,R,mid+1,pr,rs);else if(L <= mid)return query(L,R,pl,mid,ls);elsereturn query(L,R,mid+1,pr,rs);}#undef ls#undef rs
}s,t;
unsigned int hsh[N];
mt19937 rnd(time(0));
void init(){for(int i=0;i<=N-10;i++){hsh[i] = rnd();}return ;
}
int n,Q;
int main()
{IOS;init();cin >> n >> Q;for(int i=1;i<=n;i++){int x;cin >> x;s.a[i] = hsh[x];}for(int i=1;i<=n;i++){int x;cin >> x;t.a[i] = hsh[x];}s.build(1,n,1);t.build(1,n,1);while(Q -- ){int op;cin >> op;if(op == 1){int l,r,l_,r_;cin >> l >> r >> l_ >> r_;matrix S = s.query(l,r,1,n,1);matrix T = t.query(l_,r_,1,n,1);if(S == T)cout << "Yes\n";else cout << "No\n";}else if(op == 2){int p,x;cin >> p >> x;s.update(p,1,n,1,hsh[x]);}else if(op == 3){int p,x;cin >> p >> x;t.update(p,1,n,1,hsh[x]);}}return 0;
}