hdu 4046 Panda (线段树,单点更新,区间求和)

题意:

两个操作,改变区间某个位置的值,询问区间好友wbw串的个数。

题解:

将线段树的每个点的值设为以这个点为结尾的串是否是wbw。接下来就是裸的线段树。注意一个位置改变会影响三个位置,所以要更新三个位置的点。区间更新是要这样做query(a+2,b,1)因为如果不这样会重复计算。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int MOD = 1000000007;
const int maxn = 51000;
char str[maxn];
struct SegTree{
    int l, r, sum;
    int mid(){ return (l + r) >> 1; }
}tree[maxn << 2];

void push_up(int rt){
    tree[rt].sum = tree[lson].sum + tree[rson].sum;
}

bool ok(int pos){
    if (pos - 2 >= 1 && str[pos - 2] == 'w'&&str[pos - 1] == 'b'&&str[pos] == 'w')
        return true;
    return false;
}

void build(int l, int r, int rt){
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].sum = 0;
    if (l == r){
        tree[rt].sum = ok(r) ? 1 : 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, lson);
    build(mid + 1, r, rson);
    push_up(rt);
}

void update(int pos, int rt){
    if (tree[rt].l == tree[rt].r && tree[rt].r == pos){
        tree[rt].sum = ok(pos) ? 1 : 0;
        return;
    }
    int mid = tree[rt].mid();
    if (pos <= mid)
        update(pos, lson);
    else if (pos >= mid + 1)
        update(pos, rson);
    push_up(rt);
}

int query(int l, int r, int rt){
    if (l <= tree[rt].l && tree[rt].r <= r){
        return tree[rt].sum;
    }
    int res = 0;
    int mid = tree[rt].mid();
    if (l <= mid) res += query(l, r, lson);
    if (mid + 1 <= r) res += query(l, r, rson);
    return res;
}

int main(){
    //freopen("E:\\read.txt", "r", stdin);
    int n, m, T, cas = 1;
    int op, a, b;
    char c;
    scanf("%d", &T);
    while (T--){
        scanf("%d %d", &n, &m);
        scanf("%s", str + 1);
        build(1, n, 1);
        printf("Case %d:\n", cas++);
        while (m--){
            scanf("%d", &op);
            if (op == 0){
                scanf("%d %d", &a, &b);
                a++; b++;
                if (a + 2 <= b)
                    printf("%d\n", query(a + 2, b, 1));
                else
                    printf("0\n");
            }
            else{
                scanf("%d %c", &a, &c);
                a++;
                if (str[a] != c){
                    str[a] = c;
                    update(a, 1);
                    if (a + 1 <= n)
                        update(a + 1, 1);
                    if (a + 2 <= n)
                        update(a + 2, 1);
                }
            }
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值