码迷,mamicode.com
首页 > 其他好文 > 详细

P3261 [JLOI2015]城池攻占 [贪心,左偏树]

时间:2020-05-02 19:00:52      阅读:54      评论:0      收藏:0      [点我收藏+]

标签:opera   its   operator   vector   namespace   dep   pre   sdi   define   

板子吧,左偏树合并是 1log 的,按照深度合并,而且可以打 tag,pushdown。

// by Isaunoya
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct io {
	char buf[1 << 27 | 3], *s;
	int f;
	io() { f = 0, buf[fread(s = buf, 1, 1 << 27, stdin)] = ‘\n‘; }
	io& operator >> (int&x) {
		for(x = f = 0; !isdigit(*s); ++s) f |= *s  == ‘-‘;
		while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
		return x = f ? -x : x, *this;
	}
};

int n, m;
const int maxn = 3e5 + 53;
vector <int> g[maxn];
int qwq[maxn], val[maxn], mul[maxn], add[maxn];
int h[maxn];
int v[maxn], c[maxn];

int rt[maxn], ls[maxn], rs[maxn];

void down(int p, int c, int vv) {
	if(! p) return;
	v[p] *= c, v[p] += vv;
	mul[p] *= c, add[p] *= c; add[p] += vv;
}

void down(int p) {
	down(ls[p], mul[p], add[p]);
	down(rs[p], mul[p], add[p]);
	mul[p] = 1, add[p] = 0;
}

int dis[maxn];
int merge(int x, int y) {
	if(!x || !y) return x + y;
	down(x), down(y);
	if(v[x] > v[y]) swap(x, y);
	rs[x] = merge(rs[x], y);
	if(dis[ls[x]] < dis[rs[x]]) swap(ls[x], rs[x]);
	dis[x] = dis[rs[x]] + 1;
	return x;
}

int ans1[maxn], ans2[maxn];

int dep[maxn];
void dfs(int u, int f) {
	dep[u] = dep[f] + 1;
	for(int v: g[u]) dfs(v, u), rt[u] = merge(rt[u], rt[v]);
	while(rt[u] && v[rt[u]] < h[u]) {
		down(rt[u]); ++ ans1[u];
		ans2[rt[u]] = dep[c[rt[u]]] - dep[u];
		rt[u] = merge(ls[rt[u]], rs[rt[u]]);
	}
	if(qwq[u]) down(rt[u], val[u], 0);
	else down(rt[u], 1, val[u]);
}

signed main() {
#ifdef LOCAL
	freopen("testdata.in", "r", stdin);
#endif
	io in;
	in >> n >> m;
	for(int i = 1 ; i <= n ; i ++) in >> h[i];
	for(int i = 2 ; i <= n ; i ++) {
		int f;
		in >> f >> qwq[i] >> val[i];
		g[f].push_back(i);
	}
	for(int i = 1 ; i <= m ; i ++) {
		in >> v[i] >> c[i];
		mul[i] = 1;
		rt[c[i]] = merge(rt[c[i]], i);
	}
	dfs(1, 0);
	while(rt[1]) {
		down(rt[1]);
		ans2[rt[1]] = dep[c[rt[1]]];
		rt[1] = merge(ls[rt[1]], rs[rt[1]]);
	}
	for(int i = 1 ; i <= n ; i ++)
		cout << ans1[i] << ‘\n‘;
	for(int i = 1 ; i <= m ; i ++) 
		cout << ans2[i] << ‘\n‘;
	return 0;
}

P3261 [JLOI2015]城池攻占 [贪心,左偏树]

标签:opera   its   operator   vector   namespace   dep   pre   sdi   define   

原文地址:https://www.cnblogs.com/Isaunoya/p/12818874.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!