hiho 1996
解析:
观察到如果维护匹配数,空闲的0,空闲的1;具有区间可合并性
故可以用线段树求解
code
#include<bits/stdc++.h>
using namespace std;
#define fast() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define CL(a,b) memset(a,b,sizeof(a))
#define db(x) cout<<"["<<#x<<"]="<<x<<endl
/*
线段树问题:
维护区间内最大匹配数目,空闲的0的数目,空闲的1的数目
*/
int n,q;
const int maxn = 3e5+100;
struct node{
int f0,f1,mmt;
node(){}
node(int _f0,int _f1,int _mmt){
f0 = _f0, f1=_f1, mmt=_mmt;
}
}ns[maxn<<2];
int a[maxn];
void update(int root,int l,int r,int mid){
int inc = min(ns[root<<1].f1,ns[root<<1|1].f0);
ns[root].mmt = ns[root<<1].mmt+ns[root<<1|1].mmt+inc;
ns[root].f0 = ns[root<<1].f0+ns[root<<1|1].f0-inc;
ns[root].f1 = ns[root<<1].f1+ns[root<<1|1].f1-inc;
}
void build(int root,int l,int r){
if(l==r){
ns[root].f0 = (a[l]==0);
ns[root].f1 = (a[l]==1);
ns[root].mmt = 0;
return ;
}
int mid = (l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
update(root,l,r,mid);
}
void cpy(node s,node t){
t.f0=s.f0, t.f1=s.f1,t.mmt=s.mmt;
}
node query(int root,int l,int r,int a,int b){
if(a<=l&&r<=b){
return ns[root];
}
int mid = (l+r)>>1;
node n1(0,0,0);
node n2(0,0,0);
if(a<=mid){node t1 = query(root<<1,l,mid,a,b);n1=t1;}
if(b>mid){n2 = query(root<<1|1,mid+1,r,a,b);}
int inc = min(n1.f1,n2.f0);
int mmt = n1.mmt+n2.mmt+inc;
int f1 = n1.f1+n2.f1-inc;
int f0 = n1.f0+n2.f0-inc;
return node(f0,f1,mmt);
}
int main(){
fast(); cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
build(1,1,n);
//db(ns[1].mmt);
//db(ns[2].mmt);
cin>>q; int aa,bb;
for(int i=1;i<=q;i++){
cin>>aa>>bb; node t = query(1,1,n,aa,bb);
cout<<t.mmt<<endl;
}
}