[CF911G]Mass Change Queries

题目大意:给出一个数列$S(S_i\leqslant100)$,有$q$个操作,每种操作是把区间$[l,r]$中等于$x$的数改成$y$,输出答案

题解:线段树,每个节点存这段区间的每个值会变成什么,最后扫一遍就好了

卡点:

 

C++ Code:

#include <cstdio>
#define maxn 200001
int s[maxn], ans[maxn];
namespace SgT {
	int n;
	struct node {
		int s[100];
		inline node init() {for (register int i = 0; i < 100; i++) s[i] = i;}
		inline void modify(int x, int y) {for (register int i = 0; i < 100; i++) if (s[i] == x) s[i] = y;}
		inline int getnum(int x) {return s[x - 1] + 1;}
		inline node operator * (const node &rhs) const {
			node res;
			for (register int i = 0; i < 100; i++) res.s[i] = rhs.s[s[i]];
			return res;
		}
	} V[maxn << 2];
	void build(int rt, int l, int r) {
		V[rt].init();
		if (l == r) return ;
		int mid = l + r >> 1;
		build(rt << 1, l, mid);
		build(rt << 1 | 1, mid + 1, r);
	}
	inline void pushdown(int rt) {
		V[rt << 1] = V[rt << 1] * V[rt];
		V[rt << 1 | 1] = V[rt << 1 | 1] * V[rt];
		V[rt].init();
	}
	int L, R, x, y;
	void modify(int rt, int l, int r) {
		if (L <= l && R >= r) {
			V[rt].modify(x, y);
			return ;
		}
		int mid = l + r >> 1;
		pushdown(rt);
		if (L <= mid) modify(rt << 1, l, mid);
		if (R > mid) modify(rt << 1 | 1, mid + 1, r);
	}
	void add(int ll, int rr, int xx, int yy) {
		L = ll, R = rr, x = xx - 1, y = yy - 1;
		modify(1, 1, n);
	}
	void get(int rt, int l, int r) {
		if (l == r) {
			ans[l] = V[rt].getnum(s[l]);
			return ;
		}
		pushdown(rt);
		int mid = l + r >> 1;
		get(rt << 1, l, mid);
		get(rt << 1 | 1, mid + 1, r);
	}
}
using SgT::add;
int n, q;
int main() {
	scanf("%d", &n); SgT::n = n;
	for (int i = 1; i <= n; i++) scanf("%d", s + i);
	SgT::build(1, 1, n);
	scanf("%d", &q);
	for (int i = 1, l, r, x, y; i <= q; i++) {
		scanf("%d%d%d%d", &l, &r, &x, &y);
		add(l, r, x, y);
	}
	SgT::get(1, 1, n);
	for (int i = 1; i <= n; i++) {
		printf("%d", ans[i]);
		putchar(i == n ? '\n' : ' ');
	}
	return 0;
}

  

posted @ 2018-10-09 12:38  Memory_of_winter  阅读(243)  评论(0编辑  收藏  举报