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. [jQuery] 在线引用地址

    百度静态资源公共库: http://libs.baidu.com/jquery/1.9.1/jquery.js jQuery网站: http://code.jquery.com/jquery-1.9. ...

  2. java中HashMap的keySet()和values()

    我们通常说,keySet()返回所有的键,values()返回所有的值,其实是不太对的,因为无论是keySet()和values(),其实都没有实质的内容,且容我慢慢说来. 他们前者返回了一个Set, ...

  3. Lubuntu"软件包 没有可安装的候选者"解决办法

    在用VMware 安装 Lubuntu 虚拟机时,为了减少安装程序下载更新软件包的时间(安装程序默认的软件源速度较差,而且当某一软件包下载卡住,安装程序竟然要一直等待,这个过程通常会耗用大量时间,有时 ...

  4. 【VMware】VMware的安装和更改虚拟机默认存储路径

    1.VMware Workstation 14中文破解版安装 网盘下载链接:https://pan.baidu.com/s/1pbDXpgpNQTdTRzzKNWfE1A linux镜像(CentOS ...

  5. JavaScript的作用域(Scope)和上下文(Context)

    JavaScript对于作用域(Scope)和上下文(Context)的实现是这门语言的一个非常独到的地方,部分归功于其独特的灵活性. 函数可以接收不同的的上下文和作用域.这些概念为JavaScrip ...

  6. js实现选中当前元素并改变颜色(js、jq的各种循环)

    1.jq伪类选择器(:not)的使用 2.js jq运用数组循环 3.checkbox的选中循环事件 4.select的选中事件 <select class="ssss" o ...

  7. pod install 出错

    今天使用cocoapods的时候在执行pod install出错,如下: 使用很多方法都不行,但是问题感觉应该是需要升级,所有就找到升级cocoapods:sudo gem install -n /u ...

  8. Css:Conditional comments 条件注释

    http://msdn.microsoft.com/en-us/library/ms537512(VS.85).aspx http://www.quirksmode.org/css/condcom.h ...

  9. Csharp and Vbscript: Encryption/Decryption Functional

      1 /// <summary>   2     /// 塗聚文   3     /// 20130621   4     /// 自定义字符串加密解密   5     /// < ...

  10. 数据分析核心包——pandas

    一.pandas简介 pandas是一个强大的Python数据分析的工具包,是基于NumPy构建的. 1.pandas的主要功能 (1)具备对其功能的数据结构DataFrame.Series (2)集 ...