HDU - 5367 digger(線段樹區間合併 + 動態開點)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5367

題目大意:一開始有n座高度爲 r 的山峯(編號爲1~n),接下來進行q次操作,每次操作可以使得編號在[l ,r]內的山峯的高度改變d,每次操作之後,詢問有多少座山峯滿足中間一段爲連續等高的山峯,同時嚴格比這些連續的山峯的左邊和右邊的山峯要高。(編號爲1的山峯的左邊和編號爲n的山峯右邊默認爲無限高)

題目思路:本題是進行區間修改和區間查詢的,所以我們考慮用線段樹來維護。根據題目的要求我們可以知道是要維護當前節點所在的區間內連續等高的區間長度,同時維護這個區間左邊開始等高的連續區間長度,和右邊開始等高的連續區間長度,最左邊的山峯的高度,最右邊的山峯的高度,以及從最左邊開始向右邊第一座與最左邊的山峯不等高的山峯的高度,同理也要維護從最右邊開始向左邊第一座與最右邊的山峯不等高的山峯的高度。我們可以定義如下的結構體來維護這些信息:

struct Seg_Tree {
	int sum;//區間內滿足條件的山峯的數量
	int lsum, rsum;//從最左邊開始等高的山峯的區間長度,從最右邊開始等高的山峯的區間長度
	int lh, rh;//最左邊的山峯的高度,最右邊的山峯的高度
	int nlh, nrh;//從最左邊開始第一個和最左邊的山峯高度不同的山峯的高度,從最右邊開始第一個和最右邊的山峯高度不同的山峯的高度
};

然後就可以藉助線段樹的區間合併來維護這些信息了,最後的結果就是根節點的sum。

還有一個問題就是這題的n高達1e9,而且還是一個強制在線的題目。所以我們得用動態開點來維護這些信息。

具體實現看代碼:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define all(v) v.begin(),v.end()
#define clr(a) memset(a,0,sizeof(a))
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>pii;
typedef pair<int, ll>P;
const double pi = acos(-1.0);
const double eps = 1e-8;
const int MX  = 200000 + 7;
const int inf = 0x3f3f3f3f;
//head

int n, q, c;
int tot;
struct Seg_Tree {
	int sum;
	int ls, rs;
	int lsum, rsum;
	int lh, rh;
	int nlh, nrh;
	int lazy;

	void init(int l, int r) {
		lsum = rsum = r - l + 1;
		lazy = sum = lh = rh = ls = rs = nlh = nrh = 0;
	}

	void upd(int val) {
		lazy += val;
		lh += val;
		rh += val;
		nlh += val;
		nrh += val;
	}
} T[MX * 40];

void New_node(int l, int r, int &rt) {
	rt = ++tot;
	T[rt].init(l, r);
	if (l == 1) T[rt].nlh = inf;
	if (r == n) T[rt].nrh = inf;
}
void push_up(int l, int r, int rt) {
	int &ls = T[rt].ls, &rs = T[rt].rs;
	int m = (l + r) >> 1;
	if (!ls) New_node(l, m, ls);
	if (!rs) New_node(m + 1, r, rs);

	T[rt].sum = T[ls].sum + T[rs].sum;

	T[rt].lsum = T[ls].lsum;
	T[rt].rsum = T[rs].rsum;

	T[rt].lh = T[ls].lh;
	T[rt].rh = T[rs].rh;

	T[rt].nlh = T[ls].nlh;
	T[rt].nrh = T[rs].nrh;

	if (T[ls].rh == T[rs].lh) {
		int len = T[ls].rsum + T[rs].lsum;
		if (T[ls].rh > T[ls].nrh && T[ls].rh > T[rs].nlh) T[rt].sum += len;
		if (T[rt].lsum == m - l + 1) {
			T[rt].lsum += T[rs].lsum;
			T[rt].nlh = T[rs].nlh;
		}
		if (T[rt].rsum == r - m) {
			T[rt].rsum += T[ls].rsum;
			T[rt].nrh = T[ls].nrh;
		}
	} else {
		if (T[rt].lsum == m - l + 1) T[rt].nlh = T[rs].lh;
		if (T[ls].rh > T[rs].lh && T[ls].rh > T[ls].nrh) T[rt].sum += T[ls].rsum;

		if (T[rt].rsum == r - m) T[rt].nrh = T[ls].rh;
		if (T[rs].lh > T[ls].rh && T[rs].lh > T[rs].nlh) T[rt].sum += T[rs].lsum;
	}
}
void push_down(int l, int r, int rt) {
	if (T[rt].lazy) {
		int &ls = T[rt].ls, &rs = T[rt].rs;
		int m = (l + r) >> 1;
		if (!ls) New_node(l, m, ls);
		if (!rs) New_node(m + 1, r, rs);

		T[ls].upd(T[rt].lazy);
		T[rs].upd(T[rt].lazy);

		T[rt].lazy = 0;
	}
}
void update(int L, int R, int d, int l, int r, int &rt) {
	if (!rt) New_node(l, r, rt);
	if (L <= l && r <= R) {
		T[rt].upd(d);
		return;
	}
	push_down(l, r, rt);
	int m = (l + r) >> 1;
	if (L <= m) update(L, R, d, l, m, T[rt].ls);
	if (R > m) update(L, R, d, m + 1, r, T[rt].rs);
	push_up(l, r, rt);
}

int main() {
#ifdef ONLINE_JUDGE
#else
	freopen("in.txt", "r", stdin);
#endif
	while (~scanf("%d%d%d", &n, &q, &c)) {
		int root = 0; tot = 0;
		int ans = 0;
		for (int i = 1; i <= q; i++) {
			int l, r, d;
			scanf("%d%d%d", &l, &r, &d);
			l ^= ans; r ^= ans; d ^= ans;
			if (l > r) swap(l, r);
			update(l, r, d, 1, n, root);
			ans = T[root].sum;
			printf("%d\n", ans);
		}
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章