zoukankan      html  css  js  c++  java
  • BZOJ4003[JLOI2015]城池攻占(可并堆+懒惰标记)

    题面:

    火狐截图_2019-02-14T07-57-55.320Z

    思路:直接考虑每个骑士不方便,就考虑每座城池会被哪些骑士攻占。如果一个骑士到不了儿子节点,那他肯定到不了父亲节点,所以可以对每座城池建一个小根堆,维护能攻占这座城池的骑士,递归处理子树,然后把子树的堆合并进来,当堆顶骑士攻击力小于城池生命值时弹出,同时该城池的答案++。对每个骑士,可以在上述过程中记录他弹出的位置,攻占的城池数就是dep[st]-dep[ed],为方便统计,根节点深度记为1。

    注意下放标记。。。。然后先乘后加。。。。

    P.S.刚开始果断倍增,然后光荣地MLE了,不过据说3倍3倍地倍增可以减小一半内存然后AC。。。。

    代码:

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <vector>
      5 #define MAXN 300000
      6 #define MAXM 300000
      7 
      8 typedef long long LL;
      9 struct LeftistTree {
     10 	LeftistTree *son[2];
     11 	LL mul, add;
     12 	int id, d;
     13 	LeftistTree(int _id = 0) { id = _id; son[0] = son[1] = NULL; mul = 1; add = d = 0; }
     14 } * root[MAXN + 5];
     15 int a[MAXN + 5], st[MAXM + 5], end[MAXM + 5], ans[MAXN + 5], dep[MAXN + 5], N, M;
     16 LL h[MAXN + 5], v[MAXN + 5], s[MAXM + 5];
     17 std::vector<int> son[MAXN + 5];
     18 
     19 char gc();
     20 LL read();
     21 void print(LL);
     22 void dfs(int);
     23 LeftistTree *merge(LeftistTree *, LeftistTree *);
     24 LeftistTree *push(LeftistTree *, int);
     25 LeftistTree *pop(LeftistTree *);
     26 void pushDown(LeftistTree *);
     27 int top(LeftistTree *);
     28 
     29 int main() {
     30 	memset(root, 0, sizeof root);
     31 	N = read(), M = read();
     32 	for (int i = 1; i <= N; ++i)
     33 		h[i] = read();
     34 	for (int i = 2; i <= N; ++i) {
     35 		son[read()].push_back(i);
     36 		a[i] = read();
     37 		v[i] = read();
     38 	}
     39 	for (int i = 1; i <= M; ++i) {
     40 		s[i] = read(), st[i] = read();
     41 		root[st[i]] = push(root[st[i]], i);
     42 	}
     43 	dep[1] = 1;
     44 	dfs(1);
     45 	for (int i = 1; i <= N; ++i)
     46 		print(ans[i]), putchar('
    ');
     47 	for (int i = 1; i <= M; ++i)
     48 		print(dep[st[i]] - dep[end[i]]), putchar('
    ');
     49 
     50 	return 0;
     51 }
     52 inline char gc() {
     53 	static char buf[1000000], *p1, *p2;
     54 	if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);
     55 	return p1 == p2 ? EOF : *p2++;
     56 }
     57 inline LL read() {
     58 	LL res = 0, op;
     59 	char ch = gc();
     60 	while (ch != '-' && (ch < '0' || ch > '9')) ch = gc();
     61 	op = (ch == '-' ? ch = gc(), -1 : 1);
     62 	while (ch >= '0' && ch <= '9')
     63 		res = (res << 1) + (res << 3) + ch - '0', ch = gc();
     64 	return res * op;
     65 }
     66 inline void print(LL x) {
     67 	static int buf[30];
     68 	if (!x) putchar('0');
     69 	else {
     70 		if (x < 0) x = -x, putchar('-');
     71 		while (x) buf[++buf[0]] = x % 10, x /= 10;
     72 		while (buf[0]) putchar('0' + buf[buf[0]--]);
     73 	}
     74 }
     75 void pushDown(LeftistTree *rt) {
     76 	if (rt->mul > 1) {
     77 		for (int i = 0; i < 2; ++i)
     78 			if (rt->son[i]) {
     79 				rt->son[i]->mul *= rt->mul;
     80 				rt->son[i]->add *= rt->mul;
     81 				s[rt->son[i]->id] *= rt->mul;
     82 			}
     83 		rt->mul = 1;
     84 	}
     85 	if (rt->add) {
     86 		for (int i = 0; i < 2; ++i)
     87 			if (rt->son[i]) {
     88 				rt->son[i]->add += rt->add;
     89 				s[rt->son[i]->id] += rt->add;
     90 			}
     91 		rt->add = 0;
     92 	}
     93 }
     94 void dfs(int u) {
     95 	for (int i = 0; i < son[u].size(); ++i) {
     96 		dep[son[u][i]] = dep[u] + 1;
     97 		dfs(son[u][i]);
     98 		root[u] = merge(root[u], root[son[u][i]]);
     99 	}
    100 	while (1) {
    101 		if (!root[u]) break;
    102 		int p = top(root[u]);
    103 		if (s[p] >= h[u]) break;
    104 		root[u] = pop(root[u]);
    105 		ans[u]++;
    106 		end[p] = u;
    107 	}
    108 	if (root[u]) {
    109 		if (a[u]) root[u]->mul *= v[u], root[u]->add *= v[u], s[root[u]->id] *= v[u];
    110 		else root[u]->add += v[u], s[root[u]->id] += v[u];
    111 	}
    112 }
    113 LeftistTree *merge(LeftistTree *x, LeftistTree *y) {
    114 	if (!x) return y;
    115 	if (!y) return x;
    116 	if (s[x->id] > s[y->id]) std::swap(x, y);
    117 	pushDown(x);
    118 	x->son[1] = merge(x->son[1], y);
    119 	if (!x->son[0] || (x->son[1] && x->son[1]->d > x->son[0]->d))
    120 		std::swap(x->son[1], x->son[0]);
    121 	if (x->son[1]) x->d = x->son[1]->d + 1;
    122 	else x->d = 0;
    123 	return x;
    124 }
    125 LeftistTree *push(LeftistTree *rt, int v) {
    126 	LeftistTree *tmp = new LeftistTree(v);
    127 	return merge(rt, tmp);
    128 }
    129 LeftistTree *pop(LeftistTree *rt) {
    130 	pushDown(rt);
    131 	LeftistTree *res = merge(rt->son[0], rt->son[1]);
    132 	delete rt;
    133 	return res;
    134 }
    135 int top(LeftistTree *rt) {
    136 	return rt->id;
    137 }
    View Code
  • 相关阅读:
    Shiro 集成Spring 使用 redis时 使用redisTemplate替代jedisPool(五)
    shiro 实现 网站登录记住我功能 学习记录(四)
    magento2根据属性id或code来添加options
    微信小程序-注册程序app.js
    微信小程序-目录结构
    如何在最新的PHP 7.1.0上安装和运行最新的Magento 2.1.3
    添加新的php版本到wamp中
    全局使用php
    PHP设计模式之单例模式
    SourceTree使用
  • 原文地址:https://www.cnblogs.com/Rhein-E/p/10375199.html
Copyright © 2011-2022 走看看