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

题意:给定一个数,顶点有颜色。 Q次操作,或修改单点颜色,或查询路径颜色为x的个数。

思路:由于是路径,想到树剖+线段树,但是颜色个数无法合并,因此不行。  换个思路,用差分来求,然后把每个颜色弄个线段树,然后这个颜色的线段树单点代表的是这个点到根有多少这个颜色。    如果x点加了一个颜色为y的,那么以y这棵树,就再某个范围加1,这个范围是x的子树的DFS序范围;同理,减少则为-1 。

那么查询u到v路径为x颜色的个数,就在x这棵树上求sum[u]+sum[v]-sum[LCA]-sum[fa[LCA]];

自己写了一遍,感觉动态开点好像也没那么难。 但是为什么我的那么慢啊。

(颜色需要离散化。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
struct in{
int lson,rson,lazy;
in(){lson=rson=lazy=;}
}s[maxn*];
struct qqq{
char opt[]; int u,v,x;
}q[maxn<<];
int dep[maxn],a[maxn],rt[maxn*],fa[maxn][],in[maxn],ou[maxn],Log[maxn];
int Laxt[maxn],Next[maxn<<],To[maxn<<],cnt,times,b[maxn*],tot;
void add(int u,int v){
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v;
}
int LCA(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
for(int i=Log[dep[u]-dep[v]];i>=;i--)
if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
if(u==v) return u;
for(int i=;i>=;i--)
if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];
return fa[u][];
}
void dfs(int u,int f){
in[u]=++times;dep[u]=dep[f]+;
for(int i=Laxt[u];i;i=Next[i])
if(To[i]!=f) dfs(To[i],u);
ou[u]=times; fa[u][]=f;
}
void pushdown(int Now){
if(s[Now].lazy!=){
if(!s[Now].lson) s[Now].lson=++cnt;
if(!s[Now].rson) s[Now].rson=++cnt;
s[s[Now].lson].lazy+=s[Now].lazy;
s[s[Now].rson].lazy+=s[Now].lazy;
s[Now].lazy=;
}
}
void addnum(int &Now,int L,int R,int l,int r,int add){
if(!Now) Now=++cnt;
if(l<=L&&r>=R){ s[Now].lazy+=add; return ; }
int Mid=(L+R)>>; pushdown(Now);
if(l<=Mid) addnum(s[Now].lson,L,Mid,l,r,add);
if(r>Mid) addnum(s[Now].rson,Mid+,R,l,r,add);
}
int query(int Now,int L,int R,int pos){
if(!Now) return ;
if(L==R) return s[Now].lazy;
int Mid=(L+R)>>; pushdown(Now);
if(pos<=Mid) return query(s[Now].lson,L,Mid,pos);
return query(s[Now].rson,Mid+,R,pos);
}
int main()
{
int N,Q,u,v,x;
scanf("%d%d",&N,&Q); rep(i,,N) Log[i]=Log[i>>]+;
rep(i,,N) scanf("%d",&a[i]),b[++tot]=a[i];
rep(i,,N-){
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
dfs(,); cnt=;
rep(j,,)
rep(i,,N){
fa[i][j]=fa[fa[i][j-]][j-];
}
rep(i,,Q){
scanf("%s%d%d",q[i].opt,&q[i].u,&q[i].v);
if(q[i].opt[]=='Q') scanf("%d",&q[i].x),b[++tot]=q[i].x;
else b[++tot]=q[i].v;
}
sort(b+,b+tot+); tot=unique(b+,b+tot+)-(b+);
rep(i,,N) a[i]=lower_bound(b+,b+tot+,a[i])-b;
rep(i,,Q) {
if(q[i].opt[]=='Q') q[i].x=lower_bound(b+,b+tot+,q[i].x)-b;
else q[i].v=lower_bound(b+,b+tot+,q[i].v)-b;
}
rep(i,,N) addnum(rt[a[i]],,N,in[i],ou[i],);
rep(i,,Q){
u=q[i].u; v=q[i].v;
if(q[i].opt[]=='C'){
addnum(rt[a[u]],,N,in[u],ou[u],-); a[u]=v;
addnum(rt[a[u]],,N,in[u],ou[u],);
}
else {
x=q[i].x;
int Lca=LCA(u,v);
int res=query(rt[x],,N,in[u]);
res+=query(rt[x],,N,in[v]);
res-=query(rt[x],,N,in[Lca]);
res-=query(rt[x],,N,in[fa[Lca][]]);
printf("%d\n",res);
}
}
return ;
}

最新文章

  1. switch的使用
  2. JDBC代码模板
  3. iOS上传文件代码,自定义组装body
  4. edgesForExtendedLayout,automaticallyAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars的影响
  5. myeclipse的web project中使用dom4j报错java.lang.ClassNotFoundException: org.dom4j.Document
  6. Windows 8.1 系统ISO镜像下载或自Win8应用商店升级方法
  7. VIP卡
  8. Android 四大组件之三(广播)
  9. 关于android存储
  10. jQuery1.9+中删除了live以后的替代方法
  11. Java多线程技术学习笔记(二)
  12. Codeforces Round #333 (Div. 1) C. Kleof&#225;š and the n-thlon 树状数组优化dp
  13. JS学习之表格的排序
  14. Record:逻辑分区下新建简单卷后其他卷被删除
  15. oracle用户管理入门
  16. [Spring入门学习笔记][创建网站URL]
  17. ftp和mysql数据库结合使用
  18. shiro 单点登录原理 实例
  19. A - Calendar
  20. 每日英语:Nanjing&#39;s New Sifang Art Museum Illustrates China&#39;s Cultural Boom

热门文章

  1. ASP.NET 中 POST 数据并跳转页面(译自 Redirect and POST in ASP.NET)
  2. BinLog日志
  3. 转 tensorflow模型保存 与 加载
  4. (转)SQL Server中的索引结构与疑惑
  5. [sping]xml配置文件中factory-bean与factory-method(spring使用工厂方法注入bean)
  6. C# SQLite写入和读取DateTime类型
  7. 9.深入理解AbstractQueuedSynchronizer(AQS)
  8. HDU6166-求集合间的最短路
  9. Windows下查看占用端口程序
  10. 《The Cg Tutorial》阅读笔记&mdash;&mdash;凹凸贴图 Bump Mapping