hiho 1996

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;
    }
}

猜你喜欢

转载自www.cnblogs.com/fridayfang/p/11960769.html