F - 小红不想做模拟题

链接:F - 小红不想做模拟题

线段树做法

分析

  • 操作:将区间 [ l , r ] [l,r] [l,r] 全部变为1。很简单懒标记线段树即可。
  • 询问:回答 ∑ i = 1 n ( a i & b i ) \sum_{i=1}^n(a_i \& b_i) i=1n(ai&bi) 。维护一个 s u m sum sum 即可。

思路

  • 在这里插入图片描述

相信你已经看出来这个更改后的区间的 s u m sum sum 4 4 4 ,并且就是 B B B 串的 1 1 1 的个数。

  • 其实到这里已经很明了了,更改了某个串的区间那么当前区间的 s u m sum sum 就是另一个串的 1 1 1 的个数。你可以维护 c n t A ( A 串的 1 的个数 ) , c n t B ( B 串的 1 的个数 ) cnt_A(A串的1的个数),cnt_B(B串的1的个数) cntA(A串的1的个数),cntB(B串的1的个数) ,更改操作是全更改为 1 1 1 ,那么假如改的 A A A ,就 c n t A = l e n (区间长度 ) cnt_A = len(区间长度) cntA=len(区间长度) s u m sum sum 这时就取个 m i n min min 就行。
//微微风簇浪,散作满河星

#include <bits/stdc++.h>

using ll = long long;

const int N = 1e5 + 10;

#define ls i << 1
#define rs i << 1 | 1

char A[N], B[N];

struct Template {
    struct Segment {
        int l, r, sum;
        std::pair<ll, ll> pair;
        bool lz1, lz2;
    }seg[N << 2];
    
    void pushup(int i) {
        seg[i].sum = seg[ls].sum + seg[rs].sum;
        seg[i].pair = {seg[ls].pair.first + seg[rs].pair.first, seg[ls].pair.second + seg[rs].pair.second};
    }
    
    void pushdown(int i) {
        if (seg[i].lz1) {
            int len1 = seg[ls].r - seg[ls].l + 1, len2 = seg[rs].r - seg[rs].l + 1;
            seg[ls].pair.first = len1;
            seg[ls].sum = std::min(seg[ls].pair.first, seg[ls].pair.second);
            seg[ls].lz1 = true;
            seg[rs].pair.first = len2;
            seg[rs].sum = std::min(seg[rs].pair.first, seg[rs].pair.second);
            seg[rs].lz1 = true;
            seg[i].lz1 = false;
        }
        if (seg[i].lz2) {
            int len1 = seg[ls].r - seg[ls].l + 1, len2 = seg[rs].r - seg[rs].l + 1;
            seg[ls].pair.second = len1;
            seg[ls].sum = std::min(seg[ls].pair.first, seg[ls].pair.second);
            seg[ls].lz2 = true;
            seg[rs].pair.second = len2;
            seg[rs].sum = std::min(seg[rs].pair.first, seg[rs].pair.second);
            seg[rs].lz2 = true;
            seg[i].lz2 = false;
        }
    }

    void build(int i, int l, int r) {
        seg[i] = {l, r, 0, {1e9, 1e9}, false, false};
        if (l == r) {
            seg[i].pair = {A[l] - '0', B[l] - '0'};
            seg[i].sum = (A[l] - '0') bitand (B[l] - '0');
            return ;
        }
        
        int mid = l + r >> 1;
        build(ls, l, mid);
        build(rs, mid + 1, r);
        pushup(i);
    }
    
    void modify(int i, int l, int r, bool f) {
        if (l <= seg[i].l and seg[i].r <= r) {
            if (f) {
                seg[i].lz1 = true;
                seg[i].pair.first = seg[i].r - seg[i].l + 1;
                seg[i].sum = std::min(seg[i].pair.first, seg[i].pair.second);
            } else {
                seg[i].lz2 = true;
                seg[i].pair.second = seg[i].r - seg[i].l + 1;
                seg[i].sum = std::min(seg[i].pair.first, seg[i].pair.second);
            }
            return ;
        }
        pushdown(i);

        if (seg[ls].r >= l) {
            modify(ls, l, r, f);
        }
        if (seg[rs].l <= r) {
            modify(rs, l, r, f);
        }
        pushup(i);
    }
}seg;

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n;
    std::cin >> n;

    std::cin >> A + 1 >> B + 1;

    seg.build(1, 1, n);

//    std::cout << "initial: " << seg.seg[1].sum << "\n";

    int q;
    std::cin >> q;

    while (q--) {
        char op;
        int l, r;
        std::cin >> op >> l >> r;
        seg.modify(1, l, r, op == 'A');
        std::cout << seg.seg[1].sum << "\n";
    }

    return 0;
}

//
  • 17
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Heredy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值