左偏树裸题,在树上合并儿子传上来的堆,然后小于当前结点防御值的就pop掉,pop的时候统计答案.

修改的话就像平衡树一样打懒标记就行了.

具体见代码

CODE

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. char cb[1<<15],*cs=cb,*ct=cb;
  4. #define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<15,stdin),cs==ct)?0:*cs++)
  5. template<class T>inline void read(T &res) {
  6. char ch; int flg = 1; for(;!isdigit(ch=getchar());)if(ch=='-')flg=-flg;
  7. for(res=ch-'0';isdigit(ch=getchar());res=res*10+ch-'0'); res*=flg;
  8. }
  9. typedef long long LL;
  10. const int MAXN = 300005;
  11. const int MAXM = 300005;
  12. #define lc t[x].ls
  13. #define rc t[x].rs
  14. struct node {
  15. int ls, rs, d;
  16. LL v, add_tag, mul_tag;
  17. }t[MAXN];
  18. int n, m, cnt, ans1[MAXN], ans2[MAXM];
  19. int dep[MAXN], fir[MAXN], fa[MAXN], c[MAXM];
  20. LL v[MAXN], a[MAXN], h[MAXN];
  21. struct edge { int to, nxt; }e[MAXN];
  22. inline void add(int u, int v) { e[++cnt] = (edge) { v, fir[u] }, fir[u] = cnt; }
  23. vector<int> here[MAXN];
  24. inline void upd(int x) {
  25. if(t[lc].d < t[rc].d) swap(lc, rc);
  26. t[x].d = t[rc].d + 1;
  27. }
  28. inline void mt(int x) {
  29. if(t[x].mul_tag != 1) { //题目中满足只会乘正数,所以能够用堆维护
  30. if(lc)
  31. t[lc].mul_tag *= t[x].mul_tag,
  32. t[lc].add_tag *= t[x].mul_tag,
  33. t[lc].v *= t[x].mul_tag;
  34. if(rc)
  35. t[rc].mul_tag *= t[x].mul_tag,
  36. t[rc].add_tag *= t[x].mul_tag,
  37. t[rc].v *= t[x].mul_tag;
  38. t[x].mul_tag = 1;
  39. }
  40. if(t[x].add_tag) {
  41. if(lc)
  42. t[lc].add_tag += t[x].add_tag,
  43. t[lc].v += t[x].add_tag;
  44. if(rc)
  45. t[rc].add_tag += t[x].add_tag,
  46. t[rc].v += t[x].add_tag;
  47. t[x].add_tag = 0;
  48. }
  49. }
  50. int merge(int x, int y){
  51. if(!x || !y) return x + y;
  52. mt(x), mt(y);
  53. if(t[x].v > t[y].v) swap(x, y);
  54. t[x].rs = merge(t[x].rs, y);
  55. upd(x);
  56. return x;
  57. }
  58. int pop(int x) { mt(x);
  59. int l = t[x].ls, r = t[x].rs;
  60. t[x].ls = t[x].rs = t[x].add_tag = 0; t[x].mul_tag = 1;
  61. return merge(l, r);
  62. }
  63. int dfs(int x) {
  64. int rt = 0;
  65. while(!here[x].empty())
  66. rt = merge(rt, here[x].back()), here[x].pop_back();
  67. for(int i = fir[x]; i; i = e[i].nxt)
  68. dep[e[i].to] = dep[x] + 1, rt = merge(rt, dfs(e[i].to));
  69. while(rt && t[rt].v < h[x])
  70. ++ans1[x], ans2[rt] = dep[c[rt]]-dep[x], rt = pop(rt);
  71. if(rt && x > 1) {
  72. if(a[x] == 0) t[rt].v += v[x], t[rt].add_tag += v[x];
  73. else t[rt].v *= v[x], t[rt].add_tag *= v[x], t[rt].mul_tag *= v[x];
  74. }
  75. return rt;
  76. }
  77. int main() {
  78. read(n), read(m); t[0].d = -1;
  79. for(int i = 1; i <= n; ++i) read(h[i]);
  80. for(int i = 2; i <= n; ++i) read(fa[i]), read(a[i]), read(v[i]), add(fa[i], i);
  81. for(int i = 1; i <= m; ++i) read(t[i].v), read(c[i]), here[c[i]].push_back(i), t[i].mul_tag = 1;
  82. int root = dfs(1);
  83. while(root) ans2[root] = dep[c[root]] + 1, root = pop(root); //不要忘了有打通关了的骑士
  84. for(int i = 1; i <= n; ++i) printf("%d\n", ans1[i]);
  85. for(int i = 1; i <= m; ++i) printf("%d\n", ans2[i]);
  86. }

BZOJ 4003 / Luogu P3261 [JLOI2015]城池攻占 (左偏树)的更多相关文章

  1. [洛谷P3261] [JLOI2015]城池攻占(左偏树)

    不得不说,这道题目是真的难,真不愧它的“省选/NOI-”的紫色大火题!!! 花了我晚自习前半节课看题解,写代码,又花了我半节晚自习调代码,真的心态爆炸.基本上改得和题解完全一样了我才过了这道题!真的烦 ...

  2. BZOJ 4003: [JLOI2015]城池攻占 左偏树 可并堆

    https://www.lydsy.com/JudgeOnline/problem.php?id=4003 感觉就是……普通的堆啊(暴论),因为这个堆是通过递归往右堆里加一个新堆或者新节点的,所以要始 ...

  3. [JLOI2015]城池攻占 左偏树

    题目描述 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的管辖,其中 fi &l ...

  4. [luogu3261 JLOI2015] 城池攻占 (左偏树+标记)

    传送门 Description 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑士攻占 n 个城池.这 n 个城池用 1 到 n 的整数表示.除 1 号城池外,城池 i 会受到另一座城池 fi 的 ...

  5. bzoj 4003 [JLOI2015]城池攻占 —— 左偏树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4003 其实蛮简单的,首先一个城市只会被其子树中的骑士经过,启发我们 dfs 序用可并堆合并子 ...

  6. BZOJ4003 [JLOI2015]城池攻占 左偏树 可并堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4003 题意概括 题意有点复杂,直接放原题了. 小铭铭最近获得了一副新的桌游,游戏中需要用 m 个骑 ...

  7. [BZOJ4003][JLOI2015]城池攻占(左偏树)

    这题有多种做法,一种是倍增预处理出每个点往上走2^i步最少需要的初始战斗力,一种是裸的启发式合并带标记splay. 每个点合并能攻占其儿子的所有骑士,删去所有无法攻占这个城市的骑士并记录答案. 注意到 ...

  8. bzoj 4003: 城池攻占 左偏树

    题目大意 http://www.lydsy.com/JudgeOnline/problem.php?id=4003 题解 一开始看漏条件了 题目保证当占领城池可以使攻击力乘上\(v_i\)时,一定有\ ...

  9. P3261 [JLOI2015]城池攻占 (左偏树+标记下传)

    左偏树还是满足堆的性质,节点距离就是离最近的外节点(无左或者右儿子  或者二者都没有)的距离,左偏性质就是一个节点左儿子的距离不小于右儿子,由此得:节点距离等于右儿子的距离+1. 本题就是对于每个节点 ...

随机推荐

  1. GCD and LCM HDU - 4497(质因数分解)

    Problem Description Given two positive integers G and L, could you tell me how many solutions of (x, ...

  2. A/B HDU-1576(简单的数论题)

    Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). Input 数据的第一 ...

  3. centos7搭建NFS服务

    服务器端 139.155.90.78 客户端  192.168.198.146 先查看自己的系统有没有安装rpcbind 和nfs-utils rpm -qa nfs-utils rpcbind 若使 ...

  4. Dijkstra(模板)

    #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include <cstdio>//sprintf islower isupp ...

  5. FFmpeg4.0笔记:封装ffmpeg的解封装功能类CDemux

    Github https://github.com/gongluck/FFmpeg4.0-study/tree/master/Cff CDemux.h /*********************** ...

  6. INPUT和CONSTRUCT指令——范例报表查询,作用让用户输入数据,自动生成SQL的WHERE条件,带开窗查询

    INPUT指令 说明:1. 当程序执行到INPUT指令时,会将控制权交给用户,让用户输入数据.2. 用户输入完字段的数据,会将数据回传给程序中的变量接收.3. 只要执行到INPUT的指令,程序会将每个 ...

  7. Codeforces 1240B. Sequence Sorting

    传送门 分析题目发现如果把某个数 $x$ 往左移,那么之后所有小于 $x$ 的数也都要往左移 如果把 $x$ 往右移,那么之后所有大于 $x$ 的数也都要往右移 考虑我们首先一定有一个操作 $n$ 次 ...

  8. javascript——定义函数方式

    1:有名函数定义方式 2:匿名函数定义方法 https://www.cnblogs.com/wl0000-03/p/6050108.html console.log(add(3,6)); (funct ...

  9. B-Tree和 B+Tree的数据存储结构

    B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引.B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的.在讲B ...

  10. Scrapy 爬取某网站图片

    1. 创建一个 Scrapy 项目,在命令行或者 Pycharm 的 Terminal 中输入: scrapy startproject imagepix 自动生成了下列文件: 2. 在 imagep ...