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);
    }
    
  • 相关阅读:
    MySQL约束条件
    MySQL基本数据类型
    MySQL基本sql语句,存储引擎,创建表的语法,严格模式
    MySQL环境变量配置及系统服务制作,设置及修改密码,跳过授权表并重置密码,统一编码
    数据库及SQL语句由来,重要概念介绍,MySQL安装,启动服务端及连接,初识SQL语句
    图书管理系统前端页面搭建
    Bootstrap组件2
    c#版工作流之流程发起(3)
    C#版工作流运行机制(1)
    c#版本工作流引擎状态机(2)
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12575317.html
Copyright © 2011-2022 走看看