Description

给您一颗树,每个节点有个初始值。
现在支持以下两种操作:
1. C i x(0<=x<2^31) 表示将i节点的值改为x。
2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点。

Input

第一行有两个整数N,Q(1 ≤N≤ 100,000;1 ≤Q≤ 200,000),分别表示节点个数和操作个数。
下面一行N个整数,表示初始时每个节点的初始值。
接下来N-1行,每行两个整数x,y,表示x节点与y节点之间有边直接相连(描述一颗树)。
接下来Q行,每行表示一个操作,操作的描述已经在题目描述中给出。

Output

对于每个Q输出单独一行表示所求的答案。

Sample Input

5 6
10 20 30 40 50
1 2
1 3
3 4
3 5
Q 2 3 40
C 1 40
Q 2 3 40
Q 4 5 30
C 3 10
Q 4 5 30

Sample Output

0
1
1
0

正解:树链剖分+线段树。

傻逼题,直接对于每一个权值建一棵线段树,然后树剖扣路径即可。

 #include <bits/stdc++.h>
#define il inline
#define RG register
#define ll long long
#define lb(x) (x & -x)
#define N (300010) using namespace std; struct edge{ int nt,to; }g[N<<];
struct data{ int op,x,y,v; }q[N]; int head[N],top[N],fa[N],son[N],dfn[N],dep[N],sz[N],n,num,cnt;
int sum[*N],ls[*N],rs[*N],rt[N],hsh[N],a[N],tot,Sz,Q;
char ch[]; il int gi(){
RG int x=,q=; RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar();
while (ch>='' && ch<='') x=x*+ch-,ch=getchar();
return q*x;
} il void insert(RG int from,RG int to){
g[++num]=(edge){head[from],to},head[from]=num; return;
} il void dfs1(RG int x,RG int p){
fa[x]=p,dep[x]=dep[p]+,sz[x]=; RG int v;
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p) continue;
dfs1(v,x),sz[x]+=sz[v];
if (sz[son[x]]<=sz[v]) son[x]=v;
}
return;
} il void dfs2(RG int x,RG int p,RG int anc){
top[x]=anc,dfn[x]=++cnt; RG int v;
if (son[x]) dfs2(son[x],x,anc);
for (RG int i=head[x];i;i=g[i].nt){
v=g[i].to; if (v==p || v==son[x]) continue;
dfs2(v,x,v);
}
return;
} il void update(RG int &x,RG int l,RG int r,RG int p,RG int v){
if (!x) x=++Sz; if (l==r){ sum[x]+=v; return; } RG int mid=(l+r)>>;
p<=mid ? update(ls[x],l,mid,p,v) : update(rs[x],mid+,r,p,v);
sum[x]=sum[ls[x]]+sum[rs[x]]; return;
} il int query(RG int x,RG int l,RG int r,RG int xl,RG int xr){
if (xl<=l && r<=xr) return sum[x]; RG int mid=(l+r)>>;
if (xr<=mid) return query(ls[x],l,mid,xl,xr);
else if (xl>mid) return query(rs[x],mid+,r,xl,xr);
else return query(ls[x],l,mid,xl,mid)+query(rs[x],mid+,r,mid+,xr);
} il int Query(RG int u,RG int v,RG int k){
RG int ans=;
while (top[u]!=top[v]){
if (dep[top[u]]<dep[top[v]]) swap(u,v);
ans+=query(rt[k],,n,dfn[top[u]],dfn[u]),u=fa[top[u]];
}
if (dep[u]>dep[v]) swap(u,v);
ans+=query(rt[k],,n,dfn[u],dfn[v]); return ans;
} int main(){
#ifndef ONLINE_JUDGE
freopen("simple.in","r",stdin);
freopen("simple.out","w",stdout);
#endif
n=gi(),Q=gi();
for (RG int i=;i<=n;++i) a[i]=gi(),hsh[++tot]=a[i];
for (RG int i=,x,y;i<n;++i) x=gi(),y=gi(),insert(x,y),insert(y,x);
dfs1(,),dfs2(,,);
for (RG int i=;i<=Q;++i){
scanf("%s",ch);
if (ch[]=='C') q[i].op=,q[i].x=gi(); else q[i].x=gi(),q[i].y=gi();
q[i].v=gi(),hsh[++tot]=q[i].v;
}
sort(hsh+,hsh+tot+),tot=unique(hsh+,hsh+tot+)-hsh-;
for (RG int i=;i<=n;++i) a[i]=lower_bound(hsh+,hsh+tot+,a[i])-hsh,update(rt[a[i]],,n,dfn[i],);
for (RG int i=;i<=Q;++i){
q[i].v=lower_bound(hsh+,hsh+tot+,q[i].v)-hsh;
if (q[i].op) update(rt[a[q[i].x]],,n,dfn[q[i].x],-),update(rt[a[q[i].x]=q[i].v],,n,dfn[q[i].x],);
else printf("%d\n",Query(q[i].x,q[i].y,q[i].v));
}
return ;
}

bzoj4999 This Problem Is Too Simple!的更多相关文章

  1. 2019.03.09 bzoj4999: This Problem Is Too Simple!(树链剖分+线段树动态开点)

    传送门 题意:给一颗树,每个节点有个初始值,要求支持将i节点的值改为x或询问i节点到j节点的路径上有多少个值为x的节点. 思路: 考虑对每种颜色动态开点,然后用树剖+线段树维护就完了. 代码: #in ...

  2. BZOJ4999: This Problem Is Too Simple!树链剖分+动态开点线段树

    题目大意:将某个节点的颜色变为x,查询i,j路径上多少个颜色为x的点... 其实最开始一看就是主席树+树状数组+DFS序...但是过不去...MLE+TLE BY FCWWW 其实树剖裸的一批...只 ...

  3. 【BZOJ4999】This Problem Is Too Simple!(线段树)

    [BZOJ4999]This Problem Is Too Simple!(线段树) 题面 BZOJ 题解 对于每个值,维护一棵线段树就好啦 动态开点,否则空间开不下 剩下的就是很简单的问题啦 当然了 ...

  4. 【BZOJ4999】This Problem Is Too Simple! 离线+树状数组+LCA

    [BZOJ4999]This Problem Is Too Simple! Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2 ...

  5. BZOJ4999:This Problem Is Too Simple!(DFS序&树上差分&线段树动态开点:区间修改单点查询)

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

  6. 【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树

    题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) ...

  7. BZOJ4999 This Problem Is Too Simple!(树上差分+dfs序+树状数组)

    对每个权值分别考虑.则只有单点加路径求和的操作.树上差分转化为求到根的路径和,子树加即可.再差分后bit即可.注意树上差分中根的父亲是0,已经忘了是第几次因为这个挂了. #include<ios ...

  8. 4999: This Problem Is Too Simple!

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: C i x(0<=x<2^31) 表示将i节点的值改为x. Q i j x(0<=x<2^31 ...

  9. bzoj 4999: This Problem Is Too Simple!

    Description 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x&l ...

随机推荐

  1. 前端 day 039

    一 .html css js 三大基本语言 定义文档的结构:HTML  修饰文档的样式 : css  行为 : JavaScript HTML 全称 Hyper Text Mackeup Langua ...

  2. PIE SDK地图显示范围截图

    1.1. 功能简介 地图显示范围截图是将当前地图显示的范围进行输出.输出的 格式是png.bmp,主要思路就是通过IActiveView接口下的Output()方法进行输出 1.2. 功能实现说明 2 ...

  3. PIE SDK神经网络聚类

    1.算法功能简介 神经网络是模仿人脑神经系统的组成方式与思维过程而构成的信息处理系统,具有非线性.自学性.容错性.联想记忆和可以训练性等特点.在神经网络中,知识和信息的传递是由神经元的相互连接来实现的 ...

  4. oracle 基础知识(七)----动态性能视图

    一,动态性能视图介绍 动态性能视图属于数据字典,系统管理员用户 SYS 可以访问它们.在数据库打开和使用时不断进行更新,而且它们的内容主要与性能有关.虽然这些视图很像普通的数据库表,但它们不允许用户直 ...

  5. Java基础20-构造代码块

    特点: 对象一建立就运行了,而且优先于构造函数执行 作用:给对象初始化的 构造代码块和构造方法的区别: 构造方法是对应的对象进行初始化 构造代码块是给所有的对象进行统一的初始化 public clas ...

  6. 前端性能优化之优化图片 && 优化显示图片

    前端图片优化一直以来都是热门话题,从需求上来看,很多站点往往是图片体积大于代码体积, 图片请求多余代码文件请求, 给前端的性能带来了很大的困扰,那么应该如何解决呢? 零. 认识图片 我们通常使用的图片 ...

  7. PowerDesigner 16.5 安装和卸载教程【含有安装文件】

    1 下载 下载地址:https://pan.baidu.com/s/1kqly0d8qU-QluEagXwh53g 密码:n1a3 下载之后目录结构如下: 2 安装教程 1 安装 1.双击安装文件,如 ...

  8. Oracle使用sys登录时报错ORA-28009解决方法

    情况一:使用sqlplus登录: 正常输入用户名的口令,就会报错,因为SYS是在数据库之外的超级管理员,所以我们在登录的时候 要在输入口令:口令+as sysdba(比如:123456 as sysd ...

  9. nyoj1032——Save Princess——————【set应用】

    Save Princess 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 Yesterday, the princess was kidnapped by a de ...

  10. Jquery实现自动生成二级目录

    在博客园开通博客以后,就看到某位博友写的js自动生成目录的文章,当时觉得生成目录能给阅读带来方便,所以就直接拿来使用了.用了一段时间以后,发现只能生成一级目录,不能生成多级目录,有点美中不足.所以想着 ...