【BZOJ3531】旅行(树链剖分,线段树)

题面

Description

S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足

从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。

在S国的历史上常会发生以下几种事件:

”CC x c”:城市x的居民全体改信了c教;

”CW x w”:城市x的评级调整为w;

”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;

”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过

的城市的评级最大值。

由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。

Input

  1. 输入的第一行包含整数NQ依次表示城市数和事件数。
  2. 接下来N行,第i+l行两个整数WiCi依次表示记录开始之前,城市i

评级和信仰。

接下来N-1行每行两个整数x,y表示一条双向道路。

接下来Q行,每行一个操作,格式如上所述。

Output

  1. 对每个QSQM事件,输出一行,表示旅行者记下的数字。

Sample Input

  1. 5 6
  2. 3 1
  3. 2 3
  4. 1 2
  5. 3 3
  6. 5 1
  7. 1 2
  8. 1 3
  9. 3 4
  10. 3 5
  11. QS 1 5
  12. CC 3 1
  13. QS 1 5
  14. CW 3 3
  15. QS 1 5
  16. QM 2 4

Sample Output

  1. 8
  2. 9
  3. 11
  4. 3

HINT

N,Q < =10^5 , C < =10^5

数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时

刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。

题解

神题。。。

我太菜了

orz ppl

orz zsy

首先,很明显的树链剖分+线段树

对于每一个宗教开一个线段树。。。

空间受不了

换种方法来

一共就\(n\)个点

线段树显然一大堆0呀。。。

所以我要用点的时候再把这个点加上

大致的意思就是说,给线段树加上两个参

分别维护左右儿子(不再是now2和now2+1了)

如果一个区间根本都是0

那我一开始就没有必要给这个区间一个点

在修改操作的时候,我要修改哪里,如果这里没有开点

就给他赋一个点的编号就行了

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<set>
  8. #include<map>
  9. #include<vector>
  10. #include<queue>
  11. using namespace std;
  12. #define MAX 110000
  13. inline int read()
  14. {
  15. int x=0,t=1;char ch=getchar();
  16. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  17. if(ch=='-')t=-1,ch=getchar();
  18. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  19. return x*t;
  20. }
  21. struct Line
  22. {
  23. int v,next;
  24. }e[MAX<<1];
  25. int h[MAX],cnt=1;
  26. int n,m;
  27. int Q,W[MAX],C[MAX],rt[MAX];
  28. inline void Add(int u,int v)
  29. {
  30. e[cnt]=(Line){v,h[u]};
  31. h[u]=cnt++;
  32. }
  33. /*******************************************************/
  34. int dep[MAX],dfn[MAX],size[MAX],hson[MAX],fa[MAX],top[MAX],tim;
  35. void dfs1(int u,int ff)
  36. {
  37. fa[u]=ff;dep[u]=dep[ff]+1;size[u]=1;
  38. for(int i=h[u];i;i=e[i].next)
  39. {
  40. int v=e[i].v;
  41. if(v==ff)continue;
  42. dfs1(v,u);
  43. size[u]+=size[v];
  44. if(size[v]>size[hson[u]])hson[u]=v;
  45. }
  46. }
  47. void dfs2(int u,int tp)
  48. {
  49. top[u]=tp;dfn[u]=++tim;
  50. if(hson[u])dfs2(hson[u],tp);
  51. for(int i=h[u];i;i=e[i].next)
  52. {
  53. int v=e[i].v;
  54. if(v==hson[u]||v==fa[u])continue;
  55. dfs2(v,v);
  56. }
  57. }
  58. /*******************************************************/
  59. struct Node
  60. {
  61. int ls,rs;
  62. int v,ma;
  63. }t[MAX<<5];
  64. int tot,L,R;
  65. void Modify(int &now,int l,int r,int pos,int w)
  66. {
  67. if(!now)now=++tot;
  68. if(l==r){t[now].v=t[now].ma=w;return;}
  69. int mid=(l+r)>>1;
  70. if(pos<=mid)Modify(t[now].ls,l,mid,pos,w);
  71. else Modify(t[now].rs,mid+1,r,pos,w);
  72. t[now].v=t[t[now].ls].v+t[t[now].rs].v;
  73. t[now].ma=max(t[t[now].ls].ma,t[t[now].rs].ma);
  74. }
  75. int Query_Max(int now,int l,int r)
  76. {
  77. if(L<=l&&r<=R)return t[now].ma;
  78. int mid=(l+r)>>1;
  79. int ret=0;
  80. if(L<=mid&&t[now].ls)ret=max(ret,Query_Max(t[now].ls,l,mid));
  81. if(R>mid&&t[now].rs)ret=max(ret,Query_Max(t[now].rs,mid+1,r));
  82. return ret;
  83. }
  84. int Query_Sum(int now,int l,int r)
  85. {
  86. if(L<=l&&r<=R)return t[now].v;
  87. int mid=(l+r)>>1;
  88. int ret=0;
  89. if(L<=mid&&t[now].ls)ret+=Query_Sum(t[now].ls,l,mid);
  90. if(R>mid&&t[now].rs)ret+=Query_Sum(t[now].rs,mid+1,r);
  91. return ret;
  92. }
  93. /*******************************************************/
  94. int main()
  95. {
  96. n=read();Q=read();
  97. for(int i=1;i<=n;++i)W[i]=read(),C[i]=read();
  98. for(int i=1;i<n;++i)
  99. {
  100. int u=read(),v=read();
  101. Add(u,v);Add(v,u);
  102. }
  103. dfs1(1,0);dfs2(1,1);
  104. for(int i=1;i<=n;++i)Modify(rt[C[i]],1,n,dfn[i],W[i]);
  105. char ch[20];
  106. while(Q--)
  107. {
  108. scanf("%s",ch);
  109. if(ch[1]=='S')
  110. {
  111. int u=read(),v=read();
  112. int sum=0,k=rt[C[u]];
  113. while(top[u]!=top[v])
  114. {
  115. if(dep[top[u]]<dep[top[v]])swap(u,v);
  116. L=dfn[top[u]];R=dfn[u];
  117. sum+=Query_Sum(k,1,n);
  118. u=fa[top[u]];
  119. }
  120. if(dep[u]>dep[v])swap(u,v);
  121. L=dfn[u];R=dfn[v];
  122. sum+=Query_Sum(k,1,n);
  123. printf("%d\n",sum);
  124. }
  125. else if(ch[1]=='M')
  126. {
  127. int u=read(),v=read();
  128. int sum=0,k=rt[C[u]];
  129. while(top[u]!=top[v])
  130. {
  131. if(dep[top[u]]<dep[top[v]])swap(u,v);
  132. L=dfn[top[u]];R=dfn[u];
  133. sum=max(sum,Query_Max(k,1,n));
  134. u=fa[top[u]];
  135. }
  136. if(dep[u]>dep[v])swap(u,v);
  137. L=dfn[u];R=dfn[v];
  138. sum=max(sum,Query_Max(k,1,n));
  139. printf("%d\n",sum);
  140. }
  141. else if(ch[1]=='W')
  142. {
  143. int x=read(),w=read();
  144. Modify(rt[C[x]],1,n,dfn[x],w);
  145. W[x]=w;
  146. }
  147. else if(ch[1]=='C')
  148. {
  149. int x=read(),w=read();
  150. Modify(rt[C[x]],1,n,dfn[x],0);
  151. Modify(rt[w],1,n,dfn[x],W[x]);
  152. C[x]=w;
  153. }
  154. }
  155. return 0;
  156. }

【BZOJ3531】旅行(树链剖分,线段树)的更多相关文章

  1. B20J_3231_[SDOI2014]旅行_树链剖分+线段树

    B20J_3231_[SDOI2014]旅行_树链剖分+线段树 题意: S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,城市信仰不同的宗教,为了方便,我们用不同的正整数代表各种宗教. S国 ...

  2. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  4. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  7. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  8. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  9. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  10. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

随机推荐

  1. linux内核链表的使用

    linux内核链表:链表通常包括两个域:数据域和指针域.struct list_head{struct list_head *next,*prev;};include/linux/list.h中实现了 ...

  2. 小笔记:Timer定时间隔时间操作

    小笔记:Timer定时间隔时间操作,后面有时间再补充和完善: public class TimingSvc { /// <summary> /// 定时器,执行定时任务 /// </ ...

  3. PLEC-交流电机系统+笔记

    1.固有机械特性近似图 2.三相交流电机的控制系统 1)理论推导 第一次制动选择能耗制动,第二次制动选择倒拉制动. 2)模型搭建 3)模拟仿真 3.心得体会和笔记总结 制动方式的选择主要是根据各个制动 ...

  4. Git 如何 clone 非 master 分支的代码

    问题描述 我们每次使用命令 git clone git@gitlab.xxx.com:xxxxx.git 默认 clone 的是这个仓库的 master 分支.如果最新的代码不在 master 分支上 ...

  5. 8、flask之flask-script组件

    Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任 ...

  6. 架构师入门:搭建双注册中心的高可用Eureka架构(基于项目实战)

    本文的案例是基于 架构师入门:搭建基本的Eureka架构(从项目里抽取) 改写的. 在上文里,我们演示Eureka客户端调用服务的整个流程,在这部分里我们将在架构上有所改进.大家可以想象下,在上文里案 ...

  7. HTML5VEDIO标签阿里云-微信浏览器兼容性问题

    在网页展示媒体对象,离不开HTML5的 audio和video对象.但这两个目前来看兼容性方面还得关注一下. 目前在做一个阿里云下载video 并在微信端播放mp4格式的视频的时候,碰到了一些兼容性问 ...

  8. OpenStack Ironic 常见问题

    whole disk和partition 镜像 whole disk镜像部署可以支持windows,但是不能自定义分区(可以通过cloud-init实现),分区表是做镜像的人确定好的,partitio ...

  9. Linux socket网络编程基础 tcp和udp

    Socket TCP网络通信编程 首先,服务器端需要做以下准备工作: (1)调用socket()函数.建立socket对象,指定通信协议. (2)调用bind()函数.将创建的socket对象与当前主 ...

  10. eclipse快捷键及设置

    1.Eclipse设置新建菜单初始项 windows-->Perspective-->Customize Perspective--> 2.Eclipse快捷键 1. ctrl+sh ...