HDU 4339 Query (线段树+单点更新)

题意:给出两个字符串,有两个操作,一个是查询从下标 p o s pos pos开始有几个连续相同字符,一个是改变某个字符串中单个字符的值。

题解:线段树
因为查询的是从某个位置开始有几个相同字符,所以在保存和更新时就保存从左端点开始的结果,查询时也要做类似操作。见代码。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#define ll long long
using namespace std;
struct node {
	int val;
};
const int maxn = 1e6 + 10;
int t, id, q, pos, idx, len1, len2, len;
char s1[maxn], s2[maxn], x[maxn];
struct ST {
	node tree[maxn << 2];
	void build(int l, int r, int rt) {
		if (l == r) {
			if (s1[l] == s2[l]) tree[rt].val = 1;
			else tree[rt].val = 0;
		}
		else {
			int mid = (l + r) >> 1;
			build(l, mid, rt << 1);
			build(mid + 1, r, rt << 1 | 1);
			tree[rt].val = tree[rt << 1].val;
			if(tree[rt << 1].val == mid - l + 1) tree[rt].val += tree[rt << 1 | 1].val;
		}
	}
	int query(int l, int r, int L, int R, int rt) {    //L R 为查询区间
		if (r == l) {
			return tree[rt].val;
		}
		int mid = (l + r) >> 1;
		int ans = 0;
		if (L <= mid) {
			ans = query(l, mid, L, R, rt << 1);
			if (ans == mid - L + 1) ans += tree[rt << 1 | 1].val;
		}
		else {
			ans = query(mid + 1, r, L, R, rt << 1 | 1);
		}
		return ans;
	}
	void update(int pos, int v, int l, int r, int rt) {
		if (l == r) {
			tree[rt].val = v;
			return;
		}
		int mid = (l + r) >> 1;
		if (pos <= mid) {
			update(pos, v, l, mid, rt << 1);
		}
		else {
			update(pos, v, mid + 1, r, rt << 1 | 1);
		}
		tree[rt].val = tree[rt << 1].val;
		if (tree[rt << 1].val == mid - l + 1) tree[rt].val += tree[rt << 1 | 1].val;
	}
}stree;
int main() {
	scanf("%d", &t);
	int cas = 1;
	while (t--) {
		printf("Case %d:\n", cas++);
		scanf("%s%s", s1 + 1, s2 + 1);
		len1 = strlen(s1 + 1);
		len2 = strlen(s2 + 1);
		len = max(len1, len2);
		stree.build(1, len, 1);
		scanf("%d", &q);
		while (q--) {
			scanf("%d", &id);
			if(id == 2){
				scanf("%d", &pos);
				printf("%d\n", stree.query(1, len, pos + 1, pos + 1, 1));
			}
			else {
				scanf("%d%d%s", &idx, &pos, x);
				if (idx == 1) s1[pos + 1] = x[0];
				else s2[pos + 1] = x[0];
				stree.update(pos + 1, s1[pos + 1] == s2[pos + 1] ? 1 : 0, 1, len, 1);
			}
		}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值