题目描述

输入输出格式

输入格式:

输出格式:

对于每个询问操作,输出一行答案。

输入输出样例

输入样例#1:

6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
输出样例#1:

3
1
2

说明

思路:

  树剖+线段树维护区间颜色数量

来,上代码:

#include <cstdio>
#include <iostream>
#include <algorithm> #define maxn 200001 using namespace std; struct TreeNodeType {
int l,r,dis,lc,rc,flag,mid;
};
struct TreeNodeType tree[maxn<<]; struct EdgeType {
int to,next;
};
struct EdgeType edge[maxn<<]; int n,m,if_z,dis[maxn],flag[maxn],dis_[maxn];
int size[maxn],head[maxn],deep[maxn],f[maxn];
int cnt,tot,num,belong[maxn]; char Cget; inline void read_int(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
} inline void edge_add(int from,int to)
{
edge[++num].to=from,edge[num].next=head[to],head[to]=num;
edge[++num].to=to,edge[num].next=head[from],head[from]=num;
} void search(int now,int fa)
{
int pos=cnt++;
deep[now]=deep[fa]+,f[now]=fa;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fa) continue;
search(edge[i].to,now);
}
size[now]=cnt-pos;
} void search_(int now,int chain)
{
belong[now]=chain,flag[now]=++cnt;
dis_[flag[now]]=dis[now];
int pos=;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]) continue;
if(size[edge[i].to]>size[pos]) pos=edge[i].to;
}
if(pos!=) search_(pos,chain);
else return ;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==f[now]||edge[i].to==pos) continue;
search_(edge[i].to,edge[i].to);
}
} inline void tree_up(int now)
{
if(tree[now<<].rc==tree[now<<|].lc)
{
tree[now].dis=tree[now<<].dis+tree[now<<|].dis-;
}
else
{
tree[now].dis=tree[now<<].dis+tree[now<<|].dis;
}
tree[now].lc=tree[now<<].lc,tree[now].rc=tree[now<<|].rc;
} inline void tree_down(int now)
{
if(tree[now].l==tree[now].r) return ;
tree[now<<].dis=,tree[now<<|].dis=;
tree[now<<].lc=tree[now<<].rc=tree[now].flag;
tree[now<<|].lc=tree[now<<|].rc=tree[now].flag;
tree[now<<].flag=tree[now<<|].flag=tree[now].flag;
tree[now].flag=;
} void tree_build(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r;
if(l==r)
{
tree[now].lc=dis_[++cnt];
tree[now].rc=tree[now].lc;
tree[now].dis=;
return ;
}
tree[now].mid=(l+r)>>;
tree_build(now<<,l,tree[now].mid);
tree_build(now<<|,tree[now].mid+,r);
tree_up(now);
} void tree_change(int now,int l,int r,int x)
{
if(tree[now].l==l&&tree[now].r==r)
{
tree[now].dis=,tree[now].flag=x;
tree[now].lc=tree[now].rc=x;
return ;
}
if(tree[now].flag) tree_down(now);
if(l>tree[now].mid) tree_change(now<<|,l,r,x);
else if(r<=tree[now].mid) tree_change(now<<,l,r,x);
else
{
tree_change(now<<,l,tree[now].mid,x);
tree_change(now<<|,tree[now].mid+,r,x);
}
tree_up(now);
} int tree_query(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r)
{
return tree[now].dis;
}
if(tree[now].flag) tree_down(now);
tree_up(now);
if(l>tree[now].mid) return tree_query(now<<|,l,r);
else if(r<=tree[now].mid) return tree_query(now<<,l,r);
else
{
int ld=tree_query(now<<,l,tree[now].mid);
int rd=tree_query(now<<|,tree[now].mid+,r);
if(tree[now<<].rc==tree[now<<|].lc) return ld+rd-;
else return ld+rd;
}
} int tree_query_color(int now,int to)
{
if(tree[now].l==tree[now].r&&tree[now].l==to)
{
return tree[now].lc;
}
if(tree[now].flag) tree_down(now);
tree_up(now);
if(to>tree[now].mid) return tree_query_color(now<<|,to);
else return tree_query_color(now<<,to);
} inline void solve_change(int x,int y,int z)
{
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
tree_change(,flag[belong[x]],flag[x],z);
x=f[belong[x]];
}
tree_change(,min(flag[x],flag[y]),max(flag[x],flag[y]),z);
} inline int solve_query(int x,int y)
{
int ans=;
while(belong[x]!=belong[y])
{
if(deep[belong[x]]<deep[belong[y]]) swap(x,y);
ans+=tree_query(,flag[belong[x]],flag[x]);
if(tree_query_color(,flag[belong[x]])==tree_query_color(,flag[f[belong[x]]])) ans--;
x=f[belong[x]];
}
ans+=tree_query(,min(flag[x],flag[y]),max(flag[x],flag[y]));
return ans;
} int main()
{
read_int(n),read_int(m);
for(int i=;i<=n;i++) read_int(dis[i]);
int from,to,pos;
for(int i=;i<n;i++)
{
read_int(from),read_int(to);
edge_add(from,to);
}
search(,),cnt=,search_(,),cnt=,tree_build(,,n);
char type;
for(int i=;i<=m;i++)
{
cin>>type;
if(type=='C')
{
read_int(from),read_int(to),read_int(pos);
solve_change(from,to,pos);
}
else
{
read_int(from),read_int(to);
printf("%d\n",solve_query(from,to));
}
}
return ;
}

最新文章

  1. Base64编码
  2. 转:ibatis的cacheModel
  3. iis7 64位 操作excel的一系列问题(未完待续)
  4. Spirit - 腾讯移动 Web 整体解决方案
  5. hadoop启动jobhistoryserver
  6. UVa 11384 Help is needed for Dexter 正整数序列
  7. visio 改变画布大小
  8. linq 动态排序
  9. jsp带参转链接
  10. XPath总结(转)
  11. 通过CSS实现各种方向的三角形
  12. ural1090 In the Army Now
  13. 使用redis所维护的代理池抓取微信文章
  14. Linux下的 &gt;, &gt;&gt;, &lt;, ps, |, grep, /dev/null
  15. Flutter自定义路由PageRouteBuilder
  16. gRPC奇怪的编译命令protoc
  17. vue2.0 之条件渲染
  18. 【转】jquery cookie操作
  19. Spring MVC中使用errors标签
  20. oc总结 --oc基础语法相关知识

热门文章

  1. 【Git版本控制】git将单个文件回退到某一版本
  2. 3.layhm框架的流程与Boot类启动
  3. Thinkphp5 同时连接两个库
  4. python3 兔子繁殖问题
  5. python 类的封装/property类型/和对象的绑定与非绑定方法
  6. JAVA基础篇—接口实现动态创建对象
  7. 使用html+javascriptt实现的简易四则运算(初学JavaScript笔记)
  8. python基础学习笔记——列表及元组
  9. 十分钟了解HTTPS协议
  10. verilog 实现中值滤波