wannafly25 E 01串

链接 wannafly25 E 01串
  • 给出一个\(01\)串,有两种操作,操作一是将某一个位置的数字修改,操作二是询问某一个区间,将这个区间看做\(1\)个二进制数,可以随意加减\(2\)的幂次,问将这个数变为\(0\)的最小操作步数,\(n,q\leq 3*10^5\)
  • 动态dp,线段树优化\(dp\)
  • \(f_{i,01}\)表示当前在\(i\)号点,是否有进位的最小步骤,转移大力讨论。
  • 把每个转移看作一个\(2*2\)的矩阵,实际上一个\(Dp\)就是一堆矩阵的和,线段树维护矩阵和和单点修改即可。
  • 转移\[f_{i,j}=min(f_{i,0}+f_{0,j},f_{i,1}+f_{1,j})\]
  • 初始条件\[f_{0,0}=x,f_{1,1}=!x,f_{1,0}=f_{0,1}=1\]
  • 复杂度\(O(nlogn)\)
#include<bits/stdc++.h>
#define R register int
using namespace std;
const int N=300001;
int n,q,w[N],Le[N*4],Ri[N*4];char S[N];
int gi(){
    R x=0,k=1;char c=getchar();
    while(c!='-'&&(c<'0'||c>'9'))c=getchar();
    if(c=='-')k=-1,c=getchar();
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar(); 
    return x*k;
}
struct Mar{
    int s[2][2];
    void init(R x){
        s[0][0]=x,s[1][1]=(!x);
        s[1][0]=s[0][1]=1;
    }
}z,te[N*4];
Mar operator + (Mar x,Mar y){
    for(R i=0;i<=1;++i)
        for(R j=0;j<=1;++j)
            z.s[i][j]=min(x.s[i][0]+y.s[0][j],x.s[i][1]+y.s[1][j]);
    return z;
}
void build(R le,R ri,R i){
    Le[i]=le,Ri[i]=ri;
    if(le==ri){te[i].init(w[le]);return ;}
    R mid=(Le[i]+Ri[i])>>1,ls=(i<<1),rs=(ls|1);
    build(le,mid,ls),build(mid+1,ri,rs);
    te[i]=te[ls]+te[rs];
}
Mar quy(R le,R ri,R i){
    if(Le[i]==le&&Ri[i]==ri)return te[i];
    R mid=(Le[i]+Ri[i])>>1,ls=(i<<1),rs=(ls|1);
    if(ri<=mid)return quy(le,ri,ls);
    else if(le>mid)return quy(le,ri,rs);
    else return quy(le,mid,ls)+quy(mid+1,ri,rs);
}
void mdf(R pos,R v,R i){
    if(Le[i]==Ri[i]){w[pos]=v,te[i].init(v);return ;}
    R mid=(Le[i]+Ri[i])>>1,ls=(i<<1),rs=(ls|1);
    if(pos<=mid)mdf(pos,v,ls);else mdf(pos,v,rs);
    te[i]=te[ls]+te[rs];
}
int main(){
    n=gi(),scanf("%s",S+1);
    for(R i=1;i<=n;++i)w[i]=S[i]-'0';
    build(1,n,1),q=gi();
    while(q--){
        R op=gi(),u=gi(),v=gi();
        if(op==1)printf("%d\n",quy(u,v,1).s[0][0]);
        else mdf(u,v,1);
    }
    return 0;
}

转载于:https://www.cnblogs.com/Tyher/p/9871238.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值