1. 程式人生 > 實用技巧 >聯賽模擬測試20 C. Weed

聯賽模擬測試20 C. Weed


肥料吸收兩米下氮磷鉀,摻坷垃小麥畝產一萬八,日本資源埋在兩千米下,沒有坷垃日本怎麼種莊稼
一看到這道題大腦就開始放歌了

這道題可以看出操作像是一個用棧的操作,(當然更像是一個主席樹,但是主席樹好像沒有辦法統計答案,就只剩下棧了.)於是我們可以聯想到前一段做的一道線段樹維護單調棧的題目,當然這道題的棧並不單調,我們只是借用那道題的思路,對於線段樹上的每一個節點記錄一下當前節點還需要刪前面的區間多少層,這一個點裡面一共有多少層,以及這個節點可以貢獻的答案總和,每當兩個區間進行合併的時候我們討論一下,如果左兒子的總層數比右兒子要刪的層數還少直接減去貢獻即可.但是如果要大一些的話就需要我們另外寫一個函式來計算從左兒子刪去幾層後剩下的貢獻之和,需要注意的是左兒子的最後幾層有可能是沒法用的,有可能它在左區間就已經被刪掉了,於是我們查詢的是\(ask(lson, cnt - tree[rson].cnt + tree[rson].del) - ask(lson, tree[rson].del)\)

#include <cstdio>
#include <cstring>
#include <algorithm>
const int N = 1e6 + 10;
#define lson (t << 1)
#define rson (t << 1 | 1)
#define mid ((l + r) >> 1)
struct Tree {
	int sum, del, cnt;
} tree[N];
struct Que {
	int op, x;
} a[N];
int ask(int t, int cnt) {
	if(cnt <= 0) return 0;
	if(tree[t].cnt == cnt) return tree[t].sum;
	if(tree[rson].cnt >= cnt) return ask(rson, cnt);
	else return ask(lson, cnt - tree[rson].cnt + tree[rson].del) - ask(lson, tree[rson].del)+ tree[rson].sum;
}
void pushup(int t) {
	if(tree[rson].del > tree[lson].cnt) {
		tree[t].sum = tree[rson].sum;
		tree[t].del = tree[rson].del - tree[lson].cnt + tree[lson].del;
		tree[t].cnt = tree[rson].cnt;
	}
	else {
		tree[t].cnt = tree[lson].cnt + tree[rson].cnt - tree[rson].del;
		tree[t].sum = tree[lson].sum + tree[rson].sum - ask(lson, tree[rson].del);
		tree[t].del = tree[lson].del;
	}
}
void build(int t, int l, int r) {
	if(l == r) {
		tree[t].sum = a[l].op ? 0 : a[l].x;
		tree[t].del = a[l].op ? a[l].x : 0;
		tree[t].cnt = a[l].op ? 0 : 1;
		return;
	}
	build(lson, l, mid);
	build(rson, mid + 1, r);
	pushup(t);
}
void change(int t, int l, int r, int pos, int op, int x) {
	if(l == r) {
		tree[t].sum = op ? 0 : x;
		tree[t].del = op ? x : 0;
		tree[t].cnt = op ? 0 : 1;
		return;
	}
	if(pos <= mid) change(lson, l, mid, pos, op, x);
	else change(rson, mid + 1, r, pos, op, x);
	pushup(t);
}
int main() {
	freopen("weed.in", "r", stdin);
	freopen("weed.out", "w", stdout);
	int n, m;
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		a[i] = (Que){x, y};
	}
	build(1, 1, n);
	while(m--) {
		int pos, op, x;
		scanf("%d%d%d", &pos, &op, &x);
		change(1, 1, n, pos, op, x);
		printf("%d\n", tree[1].sum);
	}
	return 0;
}