uva 12345 (分段 / 树套树(好题))

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3767

开通博客的第一篇解题报告, 题目要求维护一个序列支持两种操作1. 序列的单点修改 2.查询序列区间内不同的数的个数。 本题有很多解法我打算就写下列三种: 1.分段  2.线段树套Treap 3.树状数组套主席树, 题目中的查询不好处理, 我们可以考虑把原数组转化一下, 令arr表示原数组, 定义 L数组 L[i] = max{j | j < i && A[j] = A[i]} 其实就是i左边第一个等于arr[i]的下标, 这样对于区间[l, r]的查询就变成查询数组L的区间[l, r]中有多少小于l的数字。

1.分段(Rank3!!)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>

using namespace std;

const int sz = 400;

struct Block {
	int A[605][sz + 1], B[605][sz + 1];
	int size[605];
	int n, row;

	void init(int n, int* L) {
		this->n = n;
		row = 0;
		memset(size, 0, sizeof(size));
		int r = 0, c = 0;
		for (int i = 0; i < n; i++) {
			A[r][c] = L[i];
			B[r][c] = A[r][c];
			size[r]++;
			c++;
			if (c == sz) {
				c = 0;
				r++;
			}
		}
		row = r + 1;
		for (int i = 0; i < row; i++)
			sort(B[i], B[i] + size[i]);
	}

	void modify(int p, int val) {
		int r = p / sz, c = p % sz;
		if (A[r][c] == val) return;
		int old = A[r][c];
		A[r][c] = val;
		int pos = lower_bound(B[r], B[r] + size[r], old) - B[r];
		B[r][pos] = val;
		if (val > old) {
			while (pos < size[r] - 1 && B[r][pos + 1] < B[r][pos]) {
				swap(B[r][pos], B[r][pos + 1]);
				pos++;
			}
		}
		else {
			while (pos > 0 && B[r][pos - 1] > B[r][pos]) {
				swap(B[r][pos], B[r][pos - 1]);
				pos--;
			}
		}
	}

	int query(int l, int r, int x) {
		if (r < l) return 0;
		int r1 = l / sz, r2 = r / sz;
		int c1 = l % sz, c2 = r % sz;
		int res = 0;
		if (r1 == r2) {
			while (c1 <= c2) {
				if (A[r1][c1] < x) res++;
				c1++;
			}
		}
		else {
			int tmp = size[r1];
			while (c1 < tmp) {
				if (A[r1][c1] < x) res++;
				c1++;
			}
			r1++;

			while (c2 >= 0) {
				if (A[r2][c2] < x) res++;
				c2--;
			}

			while (r1 < r2) {
				res += lower_bound(B[r1], B[r1] + size[r1], x) - B[r1];
				r1++;	
			}
		}
		return res;
	}
}key;

const int N = 100005;

#define fi first
#define se second

struct Solve {
	int L[N], arr[N];
	map<int, set<int> > Map;
	map<int, set<int> >::iterator it1;
	set<int>::iterator it2;
	int n;

	void init(int n) {
		this->n = n;
		Map.clear();
		for (int i = 0; i < n; i++) {
			scanf("%d", &arr[i]);
			if (Map.find(arr[i]) == Map.end()) {
				Map[arr[i]].insert(-1);
				Map[arr[i]].insert(n);		
			}
			Map[arr[i]].insert(i);
			it2 = Map[arr[i]].lower_bound(i);
			it2--;
			L[i] = *(it2);
		}
		key.init(n, L);
	}

	void modify(int p, int x) {
		if (arr[p] == x) return;
		int old = arr[p];
		arr[p] = x;
		Map[old].erase(p);
		int p2 = *(Map[old].upper_bound(p));
		if (p2 != n) {
			it2 = Map[old].lower_bound(p);
			it2--;
			L[p2] = *(it2);
			key.modify(p2, L[p2]);
		}
		if (Map.find(x) == Map.end()) {
			Map[x].insert(-1);
			Map[x].insert(n);
		}
		Map[x].insert(p);
		p2 = *(Map[x].upper_bound(p));
		if (p2 != n) {
			L[p2] = p;
			key.modify(p2, p);
		}
		it2 = Map[x].lower_bound(p);
		it2--;
		L[p] = *(it2);
		key.modify(p, L[p]);
	}

	int query(int l, int r) {
		return key.query(l, r, l);
	}
}sol;

int main() {
	int n, m, p, x, l, r;
	char op[3];
	scanf("%d%d", &n, &m);
	sol.init(n);
	for (int i = 0; i < m; i++) {
		scanf("%s", op);
		if (op[0] == 'Q') {
			scanf("%d%d", &l, &r);
			printf("%d\n", sol.query(l, r - 1));
		}
		else {
			scanf("%d%d", &p, &x);
			sol.modify(p, x);
		}
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值