刷个清新的数据结构题爽一爽?

题意:

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
 
注意到操作3,询问x到根的路径之间点权和,容易发现这就是欧拉序列中的前缀和。
所以按照树的欧拉序列建线段树,然后操作1就变成单点修改,操作2,就变成了区间内某些点+a,某些点-a,也容易用tag标记进行维护。
 
  1. # include <cstdio>
  2. # include <cstring>
  3. # include <cstdlib>
  4. # include <iostream>
  5. # include <vector>
  6. # include <queue>
  7. # include <stack>
  8. # include <map>
  9. # include <bitset>
  10. # include <set>
  11. # include <cmath>
  12. # include <algorithm>
  13. using namespace std;
  14. # define lowbit(x) ((x)&(-x))
  15. # define pi acos(-1.0)
  16. # define eps 1e-
  17. # define MOD
  18. # define INF
  19. # define mem(a,b) memset(a,b,sizeof(a))
  20. # define FOR(i,a,n) for(int i=a; i<=n; ++i)
  21. # define FO(i,a,n) for(int i=a; i<n; ++i)
  22. # define bug puts("H");
  23. # define lch p<<,l,mid
  24. # define rch p<<|,mid+,r
  25. # define mp make_pair
  26. # define pb push_back
  27. typedef pair<int,int> PII;
  28. typedef vector<int> VI;
  29. # pragma comment(linker, "/STACK:1024000000,1024000000")
  30. typedef long long LL;
  31. int Scan() {
  32. int x=,f=;char ch=getchar();
  33. while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
  34. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  35. return x*f;
  36. }
  37. const int N=;
  38. //Code begin...
  39.  
  40. struct Seg{LL sum, tag; int p;}seg[N<<];
  41. struct Edge{int p, next;}edge[N<<];
  42. int head[N], cnt=, node[N], pos, fdfs[N][];
  43. struct DFN{int id; bool flag;}dfn[N<<];
  44.  
  45. void add_edge(int u, int v){edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;}
  46. void dfs(int x, int fa){
  47. dfn[++pos].id=x; dfn[pos].flag=true; fdfs[x][]=pos;
  48. for (int i=head[x]; i; i=edge[i].next) {
  49. int v=edge[i].p;
  50. if (v==fa) continue;
  51. dfs(v,x);
  52. }
  53. dfn[++pos].id=x; dfn[pos].flag=false; fdfs[x][]=pos;
  54. }
  55. void push_up(int p){seg[p].p=seg[p<<].p+seg[p<<|].p; seg[p].sum=seg[p<<].sum+seg[p<<|].sum;}
  56. void push_down(int p, int L){
  57. if (!seg[p].tag) return ;
  58. seg[p].sum+=(LL)(*seg[p].p-L)*seg[p].tag;
  59. seg[p<<].tag+=seg[p].tag; seg[p<<|].tag+=seg[p].tag; seg[p].tag=;
  60. }
  61. void init(int p, int l, int r){
  62. if (l<r) {
  63. int mid=(l+r)>>;
  64. init(lch); init(rch); push_up(p);
  65. }
  66. else {
  67. seg[p].sum=dfn[l].flag?node[dfn[l].id]:-node[dfn[l].id];
  68. seg[p].p=dfn[l].flag;
  69. }
  70. }
  71. LL query(int p, int l, int r, int R){
  72. push_down(p,r-l+);
  73. if (R<l) return ;
  74. if (R>=r) return seg[p].sum;
  75. int mid=(l+r)>>;
  76. return query(lch,R)+query(rch,R);
  77. }
  78. void update1(int p, int l, int r, int X, int val){
  79. push_down(p,r-l+);
  80. if (X<l||X>r) return ;
  81. if (X==l&&X==r) seg[p].sum+=val;
  82. else {
  83. int mid=(l+r)>>;
  84. update1(lch,X,val); update1(rch,X,val); push_up(p);
  85. }
  86. }
  87. void update2(int p, int l, int r, int L, int R, int val){
  88. push_down(p,r-l+);
  89. if (L>r||R<l) return ;
  90. if (L<=l&&R>=r) seg[p].tag+=val, push_down(p,r-l+);
  91. else {
  92. int mid=(l+r)>>;
  93. update2(lch,L,R,val); update2(rch,L,R,val); push_up(p);
  94. }
  95. }
  96. int main ()
  97. {
  98. int n, m, flag, u, v;
  99. scanf("%d%d",&n,&m);
  100. FOR(i,,n) scanf("%d",node+i);
  101. FO(i,,n) scanf("%d%d",&u,&v), add_edge(u,v), add_edge(v,u);
  102. dfs(,);
  103. init(,,n<<);
  104. while (m--) {
  105. scanf("%d%d",&flag,&u);
  106. if (flag==) printf("%lld\n",query(,,n<<,fdfs[u][]));
  107. else {
  108. scanf("%d",&v);
  109. if (flag==) update1(,,n<<,fdfs[u][],v), update1(,,n<<,fdfs[u][],-v);
  110. else update2(,,n<<,fdfs[u][],fdfs[u][],v);
  111. }
  112. }
  113. return ;
  114. }

BZOJ 4034 树上操作(树的欧拉序列+线段树)的更多相关文章

  1. BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]

    题意: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 显然树链剖分可做 ...

  2. BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)

    题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...

  3. BZOJ 4034"树上操作"(DFS序+线段树)

    传送门 •题意 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的 ...

  4. HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

    lca的做法还是非常明显的.简单粗暴, 只是不是正解.假设树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的.预计就是放在splay上剖分一 ...

  5. [BZOJ 4034] 树上操作

    Link: BZOJ 4034 传送门 Solution: 树剖模板题…… Code: #include <bits/stdc++.h> using namespace std; type ...

  6. LOJ #2142. 「SHOI2017」相逢是问候(欧拉函数 + 线段树)

    题意 给出一个长度为 \(n\) 的序列 \(\{a_i\}\) 以及一个数 \(p\) ,现在有 \(m\) 次操作,每次操作将 \([l, r]\) 区间内的 \(a_i\) 变成 \(c^{a_ ...

  7. LightOJ 1370 Bi-shoe and Phi-shoe 欧拉函数+线段树

    分析:对于每个数,找到欧拉函数值大于它的,且标号最小的,预处理欧拉函数,然后按值建线段树就可以了 #include <iostream> #include <stdio.h> ...

  8. loj1370(欧拉函数+线段树)

    传送门:Bi-shoe and Phi-shoe 题意:给出多个n(1<=n<=1e6),求满足phi(x)>=n的最小的x之和. 分析:先预处理出1~1e6的欧拉函数,然后建立一颗 ...

  9. [LNOI] 相逢是问候 || 扩展欧拉函数+线段树

    原题为2017六省联考的D1T3 给出一个序列,m次操作,模数p和参数c 操作分为两种: 1.将[l,r]区间内的每个数x变为\(c^x\) 2.求[l,r]区间内数的和%p 首先,我们要了解一些数论 ...

随机推荐

  1. wmware 10 升级到11后,macos不能运行的问题

    解决方案: 1.由于wmware升级,原来的unlocker已不能使用. 所以得升级unlocker版本,目前支持wmware11的最新版本是2.0.4 http://www.insanelymac. ...

  2. 【LG5020】[NOIP2018]货币系统

    [LG5020][NOIP2018]货币系统 题面 洛谷 题解 考场上第一眼还不会233 可以发现只要可以被其他的货币通过一些奇奇怪怪的方式表示出来的货币就\(ban\)掉即可 就是个完全背包 我是统 ...

  3. 跨域发送HTTP请求详解

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客讲述几种跨域发HTTP请求的几种方法,POST请求,GET请求 目录: 一,采用JsonP的方式(只能 ...

  4. python全栈开发-前方高能-生成器和生成器表达式

    python_day_13 今日主要内容1. 生成器和生成器函数生成器的本质就是迭代器生成器的三种创建办法: 1.通过生成器函数 2.通过生成器表达式创建生成器 3.通过数据转换 生成器函数: 函数中 ...

  5. Python中的内建函数(Built_in Funtions)

    前言 在Python官方文档的标准库章节中,第一节是简介,第二节就是Built_in Functions,可见内建函数是Python标准库的重要组成部分,而有很多内建函数我们平时却很少用到或根本就不知 ...

  6. Scrapy爬豆瓣电影Top250并存入MySQL数据库

    d:进入D盘 scrapy startproject douban创建豆瓣项目 cd douban进入项目 scrapy genspider douban_spider movie.douban.co ...

  7. DataRow的RowState属性变化

    DataRow的RowState属性(状态)取值有5种:Detached, Unchanged, Added, Deleted, Modified. 当我们用DataRow newRow = Data ...

  8. Jenkins+git+Nginx

    1.Jenkins 一.tomcat安装 1.下载JDK和Tomcat //通过wget下载 wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomca ...

  9. 4星|《亿万》:FBI大战华尔街对冲基金大鳄

    亿万:围剿华尔街大白鲨 全书尝试还原2008-2013年前后FBI指控赛克资本老板科恩通过内幕交易盈利的案件细节. 作者花了数年时间,采访了200多位当事人,阅读了海量的相关资料.书中交代了科恩的发家 ...

  10. 日本IT行业劳动力缺口达22万 在日中国留学生迎来就业好时机 2017/07/18 11:25:09

    作者:倪亚敏 来源:日本新华侨报 发布时间:2017/07/18 11:25:09     据日本政府提供的数据,日本2018年应届毕业生的“求人倍率”已经达到了1.78倍.换言之,就是100名大学生 ...