小A的题 线段树区间赋值

小A需要帮助处理一个凌乱的01串,通过升序或降序局部排序进行操作。每次操作指定区间,最后输出经过m次操作后的01串状态。问题转化为维护区间1和0的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小A的题
描述

由于小 A 实在是太菜了,因此他现在需要你的帮助: 现在小 A 手上有一个凌乱的 01 串,他想通过若干次对于这个 01 串的局部排序将它变成一个有趣的 01 序列。 现在有两种操作:

输入格式

l r 00 表示把区间 [l,r][给升序排序

l r 11 表示把区间 [l,r]给降序排序

然后小 A 这个菜鸡想知道在 m次操作之后序列长啥样。

输出格式

第一行一个 01 串 S。 第二行一个整数 m。 接下来 m 行每行三个整数 l,r,x,保证 l ≤ r     a n d    x = 0 l \le r \ \ \ and \ \ x=0 lr   and  x=0 中的一个。

m 次操作之后的 01 串

数据范围
∣ S ∣ ≤ 1000000 , m ≤ 500000 ∣ S ∣ ≤ 1000000 , m ≤ 500000 |S| \le 1000000,m \le 500000∣S∣≤1000000,m≤500000 S1000000,m500000S1000000,m500000

输出时每行末尾的多余空格,不影响答案正确性

样例输入
11001
1
2 4 0
样例输出
10011

因为区间只有01,降序排序之后左边全是1,右边全是0,所以,维护区间1的个数,0的个数=区间长度-1的个数。

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f,mod=1e9+7,MAXN=1e6+4;
#define lson (i<<1)
#define rson (i<<1|1)
#define mid ((l+r)>>1)
int one[MAXN<<2],n,t;//one:1的个数
bool lazy[MAXN<<2];
char ans[MAXN];
void down(int i,int l,int r){
    one[lson]=one[i]?(mid-l+1):0;
    one[rson]=one[i]?r-mid:0;
    lazy[lson]=lazy[rson]=1;
    lazy[i]=0;
}
int sum(int x,int y,int i=1,int l=1,int r=n){
    if(x<=l&&r<=y)return one[i];
    int res=0;
    if(lazy[i])down(i,l,r);
    if(x<=mid)res+=sum(x,y,lson,l,mid);
    if(y>mid)res+=sum(x,y,rson,mid+1,r);
    return res;
}
void up(int i,int l,int r){
    one[i]=one[lson]+one[rson];
}
void change(int x,int y,int val,int i=1,int l=1,int r=n){
    if(x>y)return;
    if(x<=l&&r<=y){
        lazy[i]=1;
        one[i]=val?r-l+1:0;
        return;
    }
    if(lazy[i])down(i,l,r);
    if(x<=mid)change(x,y,val,lson,l,mid);
    if(y>mid)change(x,y,val,rson,mid+1,r);
    up(i,l,r);
}
void build(int i=1,int l=1,int r=n){
    if(l==r){
        if(ans[l]=='1')one[i]=1;
        return;
    }
    build(lson,l,mid);
    build(rson,mid+1,r);
    up(i,l,r);
}
void print(int i=1,int l=1,int r=n){
        if(l==r){
        putchar(one[i]+48);
        return;
    }
if(lazy[i])down(i,l,r);
   print(lson,l,mid);
    print(rson,mid+1,r);
}
int main() {
    char ch=getchar();
    while(ch!='\n'){
        ans[++n]=ch;
        ch=getchar();
    }
    build();
    scanf("%d",&t);
    int x,y,op,yi,m;
    while(t--){
        scanf("%d%d%d",&x,&y,&op);
        if(x>y)continue;
        yi=sum(x,y);
        if(!yi||y-x+1==yi)continue;
        if(op==1){
            m=yi+x-1;
            change(x,m,1);
            change(m+1,y,0);
        }else if(op==0){
            m=y-yi;
            change(x,m,0);
            change(m+1,y,1);
        }
    }
	print();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值