interlinkage:

https://jzoj.net/senior/#main/show/3175

description:

给定一棵N 个节点的树,标号从1~N。每个点有一个权值。要求维护两种操作:
1. C i x(0<=x<2^31) 表示将i 点权值变为x
2. Q i j x(0<=x<2^31) 表示询问i 到j 的路径上有多少个值为x的节点

solution:

  • 链剖
  • 把颜色离散化,对每种颜色分别搞一颗线段树
  • 直接搞会炸空间,因此要动态开点
  • 感觉树上莫队好像也可以

code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll; const int N=4e5+;
int n,q,tot,cnt,tim;
int head[N],dep[N],siz[N],wson[N],fa[N],top[N],dfn[N],rt[N<<],color[N];
int lx[N<<],rx[N<<],sum[N<<];
ll a[N],b[N<<];
struct EDGE
{
int to,nxt;
}edge[N];
struct QUE
{
int op;
int x,y;
ll v;
}t[N];
inline ll read()
{
char ch=getchar();ll s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void add(int u,int v)
{
edge[++tot]=(EDGE){v,head[u]};
head[u]=tot;
}
void dfs1(int x,int pre)
{
dep[x]=dep[pre]+;siz[x]=;fa[x]=pre;
for (int i=head[x];i;i=edge[i].nxt)
{
int y=edge[i].to;
if (y==pre) continue;
dfs1(y,x);
siz[x]+=siz[y];
if (!wson[x]||siz[wson[x]]<siz[y]) wson[x]=y;
}
}
void dfs2(int x,int tp)
{
top[x]=tp;dfn[x]=++tim;
if (wson[x]) dfs2(wson[x],tp);
for (int i=head[x];i;i=edge[i].nxt)
{
int y=edge[i].to;
if (y==fa[x]||y==wson[x]) continue;
dfs2(y,y);
}
}
void upd(int o)
{
sum[o]=sum[lx[o]]+sum[rx[o]];
}
void update(int &o,int l,int r,int pos,int x)
{
if (!o) o=++cnt;
if (l==r)
{
sum[o]+=x;
return;
}
int mid=l+r>>;
if (pos<=mid) update(lx[o],l,mid,pos,x);
else update(rx[o],mid+,r,pos,x);
upd(o);
}
void change(int x,int v)
{
if (color[x])
{
update(rt[color[x]],,n,dfn[x],-);
}
color[x]=v;
update(rt[v],,n,dfn[x],);
}
int query(int o,int l,int r,int x,int y)
{
if (!o) return ;
if (l>=x&&r<=y) return sum[o];
int mid=l+r>>,re=;
if (x<=mid) re+=query(lx[o],l,mid,x,y);
if (y>mid) re+=query(rx[o],mid+,r,x,y);
return re;
}
int query_path(int x,int y,int v)
{
int res=;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
res+=query(rt[v],,n,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if (dep[x]<dep[y]) swap(x,y);
res+=query(rt[v],,n,dfn[y],dfn[x]);
return res;
}
int main()
{
//freopen("tree.in","r",stdin);
n=read();q=read();
int len=;
for (int i=;i<=n;i++) a[i]=read(),b[++len]=a[i];
for (int i=;i<n;i++)
{
int u=read(),v=read();
add(u,v);add(v,u);
}
dfs1(,);
dfs2(,);
char s[];
for (int i=;i<=q;i++)
{
scanf("%s",s);
if (s[]=='C')
{
t[i].op=;
t[i].x=read();t[i].v=read();
}
if (s[]=='Q')
{
t[i].op=;
t[i].x=read();t[i].y=read();t[i].v=read();
}
b[++len]=t[i].v;
}
sort(b+,b++len);
len=unique(b+,b++len)-b-;
for (int i=;i<=n;i++) a[i]=lower_bound(b+,b++len,a[i])-b;
for (int i=;i<=q;i++) t[i].v=lower_bound(b+,b++len,t[i].v)-b;
for (int i=;i<=n;i++) change(i,a[i]);
for (int i=;i<=q;i++)
{
if (t[i].op==)
{
change(t[i].x,t[i].v);
}
if (t[i].op==)
{
printf("%d\n",query_path(t[i].x,t[i].y,t[i].v));
}
}
return ;
}

[jzoj 3175] 数树数 解题报告 (树链剖分)的更多相关文章

  1. 【九度OJ】题目1176:树查找 解题报告

    [九度OJ]题目1176:树查找 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1176 题目描述: 有一棵树,输出某一深度的所有节点 ...

  2. (持续更新)虚树,KD-Tree,长链剖分,后缀数组,后缀自动机

    真的就是讲课两天,吸收一个月呢! \(1.\)虚树 \(2.\)KD-Tree \(3.\)长链剖分 \(4.\)后缀数组 后缀数组 \(5.\)后缀自动机 后缀自动机

  3. [BZOJ2243][SDOI2011]染色 解题报告|树链剖分

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

  4. [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分

    树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...

  5. [POJ3237]Tree解题报告|树链剖分|边剖

    关于边剖 之前做的大多是点剖,其实转换到边剖非常简单. 我的做法是每个点的点权记录其到父亲节点的边的边权. 只要solve的时候不要把最上面的点记录在内就可以了. Tree Description Y ...

  6. HDU 1754 线段树入门解题报告

    ---恢复内容开始--- 题意:给定区间,每个人的成绩, Q次询问,求每次询问区间中的最大值 思路:构造线段树 代码: #include<stdio.h> #include<algo ...

  7. POJ 3264 线段树入门解题报告

    题意:给n个值, Q次询问, 每次询问给定一个区间, 要求输出该区间最大最小值之差 思路:暴力的话每次询问都要遍历多次for循环一定会超时, 用线段树记录区间的信息(左边界右边界, 该区间最大值最小值 ...

  8. [NOIP2016 DAY1 T2]天天爱跑步-[差分+线段树合并][解题报告]

    [NOIP2016 DAY1 T2]天天爱跑步 题面: B[NOIP2016 DAY1]天天爱跑步 时间限制 : - MS 空间限制 : 565536 KB 评测说明 : 2s Description ...

  9. 洛谷 P3373 【模板】线段树 2 解题报告

    P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上\(x\) 2.将某区间每一个数加上\(x\) 3.求出某区间每一个数的和 输入输出格式 ...

随机推荐

  1. C-字符串和格式化输入\输出

    1.字符串是一个或多个字符序列.字符串常量用双引号括起来“abc”,字符常量用单引号括起来‘’. 2.数组是同一类型的数据元素的有序序列.数据元素在内存中是连续存储的. C中没有为字符串定义专门的变量 ...

  2. 错误:android.util.SuperNotCalledException

    android.util.SuperNotCalledException: Activity {…….YouTubePlayActivity} did not call through to supe ...

  3. mongoDB 介绍(特点、优点、原理)

    介绍:MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. 特点:高性能.易部署.易使用,存储数据非常方便. 主要功能特性有: Ø 面 ...

  4. word2016如何英汉互译

    1.如果是一篇英文文档且是pdf格式,可以用word2016打开直接转化成了word,就算不是会员也可以的,在此附上16版的光盘安装包,可以百度自行下载 (链接:https://pan.baidu.c ...

  5. Pycharm 4.5.4 for ubuntu 16.04 下载与安装教程

    首先,我们需要有一台已经安装好 ubuntu 16.04 的操作系统,并且配置好java环境: 方法1: 默认安装 apt-get install default-jdk -y # 安装官网最新的ja ...

  6. 阿里云API网关!

    API 网关(API Gateway)提供高性能.高可用的 API 托管服务,帮助用户对外开放其部署在 ECS.容器服务等阿里云产品上的应用,提供完整的 API 发布.管理.维护生命周期管理.用户只需 ...

  7. 百面机器学习--跟课Task整理

    涉及书中内容:特征工程&&模型评估 不同的特征如何进行特征工程? 特征是原始数据作为输入,特征工程的结果,作为输入供算法和模型使用. 对于数值型特征,为消除特征间的量纲影响,应对特征进 ...

  8. Disconf使用简单Demo

    创建配置文件 在敲Demo之前,需要在Disconf上创建自己的APP,然后在APP的某个环境下创建配置文件,如下面截图中的流程,这里就简单创建了一个redis.properties,内容是redis ...

  9. WSDL实例解析

    WSDL的主要文档元素 WSDL文档可以分为两部分.顶部分由抽象定义组成,而底部分则由具体描述组成.抽象部分以独立于平台和语言的方式定义SOAP消息,它们并不包含任何随 机器或语言而变的元素.这就定义 ...

  10. POJ3984-迷宫问题【BFS】

    定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, ...