zoukankan      html  css  js  c++  java
  • BJOI2018二进制

    线段树好题


    (n,m,1e5)

    二进制没有位除3的余数是以12121212……循环的

    我们用总数减去不合法情况:

    1. 只有1个1,0的个数>=2(保证不重复)
    2. 奇数个1,0的个数<2

    考虑用线段树解决

    每一点存

    (dl[0/1][0/1]),左端点起,0的个数,1的个数的偶奇的方案数,(dr)同理

    (fl[0/1/2]),左端点起,一个1,0/1/>=2个0的方案数,(fr)同理

    在记录0/1的个数,左起/右起0的个数,答案

    讨论更新即可

    时间复杂度(O(nlog_n))

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    const int N=1e5+4;
    struct node{
    	int dl[2][2],dr[2][2],fl[3],fr[3],s0,s1,l0,r0,s;
    	//左端点起 0出现次数0/1 1的奇偶1/0  左端点起1的个数1个0的个数0/1/>=2
    	inline void init(){
    		memset(dl,0,sizeof(dl));
    		memset(dr,0,sizeof(dr));
    		memset(fl,0,sizeof(fl));
    		memset(fr,0,sizeof(fr));
    		s0=s1=l0=r0=s=0;
    	} 
    	node(){init();}
    	inline void pre(int x){
    		init();
    		if(x)dl[0][1]=dr[0][1]=fl[0]=fr[0]=s1=s=1;
    		else dl[1][0]=dr[1][0]=s0=l0=r0=1;
    	}
    	inline node operator +(const node &a)const{
    		static node ret;
    		memcpy(ret.dl,dl,sizeof(dl));
    		memcpy(ret.fl,fl,sizeof(fl));
    		memcpy(ret.dr,a.dr,sizeof(a.dr));
    		memcpy(ret.fr,a.fr,sizeof(a.fr));
    		for(int i=0;i+s0<2;i++)
    			for(int v=0;v^2;v++)
    				ret.dl[s0+i][v^(s1&1)]+=a.dl[i][v];
    		for(int i=0;i+a.s0<2;i++)
    			for(int v=0;v^2;v++)
    				ret.dr[a.s0+i][v^(a.s1&1)]+=dr[i][v];
    		for(int i=0;i<3;i++){
    			if(!s1)ret.fl[min(2ll,i+s0)]+=a.fl[i];
    			if(!a.s1)ret.fr[min(2ll,i+a.s0)]+=fr[i];
    		}
    		if(s1==1&&a.l0){
    			ret.fl[min(2ll,s0+a.l0)]+=1;
    			ret.fl[2]+=a.l0-1;
    		}
    		if(a.s1==1&&r0){
    			ret.fr[min(2ll,a.s0+r0)]+=1;
    			ret.fr[2]+=r0-1;
    		}
    		ret.l0=l0+(!s1?a.l0:0);//括号括起来 
    		ret.r0=a.r0+(!a.s1?r0:0);
    		ret.s0=s0+a.s0;
    		ret.s1=s1+a.s1;
    		ret.s=s+a.s;
    		ret.s+=dr[0][0]*(a.dl[0][1]+a.dl[1][1])+dr[0][1]*(a.dl[0][0]+a.dl[1][0])+dr[1][0]*a.dl[0][1]+dr[1][1]*a.dl[0][0];
    		if(r0)ret.s+=r0*(a.fl[0]+a.fl[1]+a.fl[2])-a.fl[0];
    		if(a.l0)ret.s+=a.l0*(fr[0]+fr[1]+fr[2])-fr[0];
    		return ret;
    	}
    }t[N<<2];
    #define lc (p<<1)
    #define rc (p<<1|1)
    int n,m,a[N<<2];
    void build(int p,int l,int r){
    	if(l==r){
    		t[p].pre(a[l]);
    		return;
    	}
    	int mid=l+r>>1;
    	build(lc,l,mid);
    	build(rc,mid+1,r);
    	t[p]=t[lc]+t[rc];
    } 
    void modify(int p,int l,int r,int x){
    	if(l==r){
    		t[p].pre(a[l]);
    		return;
    	}
    	int mid=l+r>>1;
    	if(x<=mid)modify(lc,l,mid,x);
    	else modify(rc,mid+1,r,x);
    	t[p]=t[lc]+t[rc];
    }
    node query(int p,int l,int r,int ql,int qr){
    	if(ql<=l&&r<=qr)return t[p];
    	int mid=l+r>>1;
    	if(qr<=mid)return query(lc,l,mid,ql,qr);
    	if(mid<ql)return query(rc,mid+1,r,ql,qr);
    	return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
    }
    signed main(){
    	n=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	build(1,1,n);
    	m=read();
    	while(m--){
    		static int op,x,y;
    		op=read();x=read();
    		if(op==1){
    			a[x]^=1;
    			modify(1,1,n,x);
    		}
    		else{
    			y=read();
    			cout<<(y-x+1)*(y-x+2)/2-query(1,1,n,x,y).s<<"
    ";
    		}
    	}
    	return (0-0);
    }
    
  • 相关阅读:
    ReactiveCocoa 谈谈RACMulticastConnection
    ReactiveCocoa 谈谈concat
    Swift 一些环境配置
    hpple 简单使用
    Swift 学习手记1,pod 的 类库使用
    [转]SQL语句:Group By总结
    Jquery VailDate初探
    C#RSA加密解密详解
    电子印章制作管理系统 -升级版本
    tensorflow 实现的第一个目标检测模型
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12575317.html
Copyright © 2011-2022 走看看