rt,5e5给根号好像也不是很抽象。
思路是用数组记录段内多余的买入点数量和多余的卖出点数量,发现不好删除,然后回滚。
代码如下。
#include<bits/stdc++.h>
#define fir first
#define sec second
#define maxn 500005
#define block 850
#ifdef ONLINE_JUDGE
#define getchar() getchar_unlocked()
#define puchar(ch) putchar_unlocked(ch)
#endif
using namespace std;
inline int read(){
int x=0,w=0;
char ch=' ';
while(!isdigit(ch)){
if(ch=='-')
w=1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-'0';
ch=getchar();
}
return (w?-x:x);
}
int __fastwrite_stack[45],__fastwrite_top;
inline void write(int x){
__fastwrite_top=0;
do{
__fastwrite_stack[__fastwrite_top++]=x%10;
x/=10;
}while(x);
while(__fastwrite_top--)putchar(__fastwrite_stack[__fastwrite_top]+'0');
}
int n,q;
int a[maxn],c[maxn];
int is[maxn],ed[maxn],tot;
int ans[maxn];
struct query{
int l,r,from;
bool operator <(const query&other){
return r<other.r;
}
};
vector<query>m[maxn];
query cg[maxn*2];
int cnt[maxn][2];
//0:多余买入点,1:多余卖出点
int l[maxn],r[maxn],CNT[maxn];
int lst[maxn],TOT;
signed main(){
// freopen("PCR.in","r",stdin);
// freopen("nothing.out","w",stdout);
cin>>n>>q;
for(int i=1;i<=n;i++){
a[i]=read();
is[i]=tot=i/block;
ed[is[i]]=i;
}
for(int i=1;i<=n;i++){
c[i]=read();
if(!lst[c[i]])
lst[c[i]]=++TOT;
c[i]=lst[c[i]];
}
for(int i=1;i<=q;i++){
l[i]=read();r[i]=read();
CNT[is[l[i]]]++;
}
for(int i=0;i<=tot;i++)m[i].resize(CNT[i]);
for(int i=1;i<=q;i++){
m[is[l[i]]][--CNT[is[l[i]]]]={l[i],r[i],i};
//放入左端点所在块中
}
for(int i=0;i<=tot;i++){
//逐块处理
memset(cnt,0,sizeof cnt);
sort(m[i].begin(),m[i].end());
int l=ed[i],r=ed[i]-1,as=0;
for(auto it:m[i]){
while(r<it.r){
int j=++r;
if(a[j]){
//右侧卖出看又没有可匹配的买入点
if(cnt[c[j]][0]){
cnt[c[j]][0]--;
as++;
}else{
cnt[c[j]][1]++;
}
}else{
cnt[c[j]][0]++;
}
}
int st=as,ct=0;
if(it.r<ed[i]){
//同一块内直接处理
for(int j=it.l;j<=it.r;j++){
if(a[j]==0){
cnt[c[j]][0]++;
cg[++ct]={c[j],0,1};
//右侧买入点直接加
}else{
//卖入点看又没有可匹配的买入点
if(cnt[c[j]][0]){
cnt[c[j]][0]--;
cg[++ct]={c[j],0,-1};
as++;
}
}
}
}else{
//左端点左移
for(int j=l-1;j>=it.l;j--){
if(a[j]==0){
if(cnt[c[j]][1]){
cnt[c[j]][1]--;
cg[++ct]={c[j],1,-1};
as++;
}else{
cnt[c[j]][0]++;
cg[++ct]={c[j],0,1};
}
}else{
cnt[c[j]][1]++;
cg[++ct]={c[j],1,1};
}
}
}
//清空左端点影响
for(int j=1;j<=ct;j++)
cnt[cg[j].l][cg[j].r]-=cg[j].from;
ans[it.from]=as;
as=st;
}
}
for(int i=1;i<=q;i++){
write(ans[i]);
putchar('\n');
}
return 0;
}