傳送門
解題思路
對於每個人的棋子,總是最高的那個棋子發揮決定性作用,被消耗後,再看剩下的最高的棋子。這就相當於單調不遞增棧的維護過程。
最後就要比較兩個人的單調不遞增棧是否完全相同。
和經典的樓房重建相似,但是這個題不止需要維護單調棧的長度,還要維護哈希值。
我是分開寫的,但是實際上可以直接用pair表示哈希值和長度,寫起來條理一些。
順便我把序列倒過來了(爲了和樓房重建重合度大一些)
AC代碼
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<ctime>
#include<stack>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!(c>='0'&&c<='9')) {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
const int maxn=2e5+5;
const int mod=1e9+7;
int d[2][maxn*4],len[2][maxn*4],n,m,a[2][maxn];
long long Hash[2][maxn*4],mi[maxn];
int getans(int op,int id,int l,int r,int v){
if(l==r) return d[op][id]>=v;
if(d[op][id]<v) return 0;
int mid=(l+r)/2;
if(d[op][id*2]>=v) return getans(op,id*2,l,mid,v)+len[op][id]-len[op][id*2];
return getans(op,id*2+1,mid+1,r,v);
}
long long gethash(int op,int id,int l,int r,int v){
if(l==r) return d[op][id]>=v?Hash[op][id]:0;
if(d[op][id]<v) return 0;
int mid=(l+r)/2;
if(d[op][id*2]>=v) return (gethash(op,id*2,l,mid,v)*mi[len[op][id]-len[op][id*2]]+(Hash[op][id]-Hash[op][id*2]*mi[len[op][id]-len[op][id*2]])%mod+mod)%mod;
return gethash(op,id*2+1,mid+1,r,v);
}
void pushup(int op,int id,int l,int r){
int mid=(l+r)/2;
d[op][id]=max(d[op][id*2],d[op][id*2+1]);
int x=getans(op,id*2+1,mid+1,r,d[op][id*2]);
long long y=gethash(op,id*2+1,mid+1,r,d[op][id*2]);
len[op][id]=len[op][id*2]+x;
Hash[op][id]=(Hash[op][id*2]*mi[x]+y)%mod;
return;
}
void add(int op,int id,int l,int r,int x,int v){
if(l==r){
d[op][id]=v;
len[op][id]=1;
Hash[op][id]=v%mod;
return;
}
int mid=(l+r)/2;
if(x<=mid) add(op,id*2,l,mid,x,v);
else add(op,id*2+1,mid+1,r,x,v);
pushup(op,id,l,r);
}
int main()
{
mi[0]=1;
for(int i=1;i<=200000;i++) mi[i]=mi[i-1]*998244353%mod;
n=read();
for(int i=n;i>=1;i--){
a[0][i]=read();
add(0,1,1,n,i,a[0][i]);
}
m=read();
for(int i=m;i>=1;i--){
a[1][i]=read();
add(1,1,1,m,i,a[1][i]);
}
int T=read();
while(T--){
int op=read(),x=read(),y=read();
if(op==1) add(0,1,1,n,n-x+1,y),a[0][n-x+1]=y;
else add(1,1,1,m,m-x+1,y),a[1][m-x+1]=y;
if(Hash[0][1]==Hash[1][1]) puts("YES");
else puts("NO");
}
return 0;
}