题目连接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/D

题意:给定一棵有n个节点的无根树及点权和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段);

分析:树链剖分将信息映射到线段树后,线段树则要维护区间的两个端点值,在区间合并时”左孩子的右端点“与“右孩子的左端点”相同时总数减一。。。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std; struct edge
{
int to,next;
edge(){}
edge(int to,int next):to(to),next(next){}
}e[N<<];
int head[N<<],tot;
int top[N];//top[v]表示v所在的重链的顶端节点
int fa[N];//父亲节点
int dep[N];//深度
int sz[N];//si[v]表示以v为根节点的子树的节点数
int son[N];//重儿子
int p[N];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[N];//与p数组相反
int pos;//所有链构成的线段树总长度
int sum[N<<],col[N<<],lc[N<<],rc[N<<],a[N];
void addedge(int u,int v)
{
e[tot]=edge(v,head[u]);
head[u]=tot++;
}
void init()
{
tot=;FILL(head,-);
pos=;FILL(son,-);
}
void dfs(int u,int f,int d)
{
dep[u]=d;sz[u]=;fa[u]=f;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v==f)continue;
dfs(v,u,d+);
sz[u]+=sz[v];
if(son[u]==-||sz[son[u]]<sz[v])son[u]=v;
}
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=++pos;
fp[pos]=u;
if(son[u]==-)return;
getpos(son[u],sp);
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u])
{
getpos(v,v);
}
}
}
void Pushup(int rt)
{
int ls=rt<<,rs=ls|;
sum[rt]=sum[ls]+sum[rs];
lc[rt]=lc[ls];rc[rt]=rc[rs];
if(lc[rs]==rc[ls])sum[rt]--;
}
void Pushdown(int rt)
{
if(col[rt])
{
int ls=rt<<,rs=ls|;
col[ls]=col[rs]=col[rt];
sum[ls]=sum[rs]=;
lc[ls]=rc[ls]=lc[rs]=rc[rs]=col[rt];
col[rt]=;
}
}
void build(int l,int r,int rt)
{
col[rt]=;
if(l==r)
{
lc[rt]=rc[rt]=a[fp[l]];
sum[rt]=;
return;
}
int m=(l+r)>>;
build(lson);
build(rson);
Pushup(rt);
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
lc[rt]=rc[rt]=c;
sum[rt]=;col[rt]=c;
return;
}
Pushdown(rt);
int m=(l+r)>>;
if(L<=m)update(L,R,c,lson);
if(m<R)update(L,R,c,rson);
Pushup(rt);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return sum[rt];
Pushdown(rt);
int m=(l+r)>>;
int res=;
if(R<=m)res=query(L,R,lson);
else if(L>m)res=query(L,R,rson);
else
{
res=query(L,m,lson)+query(m+,R,rson);
if(rc[rt<<]==lc[rt<<|])res--;
}
return res;
}
int query1(int ps,int l,int r,int rt)
{
if(l==r)
return lc[rt];
Pushdown(rt);
int m=(l+r)>>;
if(ps<=m)return query1(ps,lson);
else return query1(ps,rson);
}
void update_tree(int u,int v,int c)
{
int fu=top[u],fv=top[v];
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
swap(fu,fv);
swap(u,v);
}
update(p[fu],p[u],c,,pos,);
u=fa[fu];fu=top[u];
}
if(dep[u]>dep[v])swap(u,v);
update(p[u],p[v],c,,pos,);
}
int lca(int u,int v)
{
int fu=top[u],fv=top[v];
int res=;
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
swap(fu,fv);
swap(u,v);
}
res+=query(p[fu],p[u],,pos,);
if(query1(p[fu],,pos,)==query1(p[fa[fu]],,pos,))res--;
u=fa[fu];fu=top[u];
}
if(dep[u]>dep[v])swap(u,v);
res+=query(p[u],p[v],,pos,);
return res;
}
int main()
{
int n,m,u,v,w;
char op[];
while(scanf("%d%d",&n,&m)>)
{
init();
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs(,,);
getpos(,);
build(,pos,);
while(m--)
{
scanf("%s",op);
if(op[]=='C')
{
scanf("%d%d%d",&u,&v,&w);
update_tree(u,v,w);
}
else
{
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
}
}
}

HYSBZ 2243(树链剖分)的更多相关文章

  1. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  2. HYSBZ - 2243 树链剖分 + 线段树 处理树上颜色段数

    用线段树处理颜色段数 记录区间内的颜色段数,区间右端点的颜色,区间右端点的颜色. int tr[maxn<<2], lc[maxn<<2], rc[maxn<<2] ...

  3. bzoj 2243 树链剖分

    2013-11-19 16:21 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分,用线段树记录该区间的颜色段数,左右端点颜 ...

  4. HYSBZ 1036树链剖分

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从 ...

  5. BZOJ 2243: [SDOI2011]染色 (树链剖分+线段树合并)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分的点剖分+线段树.漏了一个小地方,调了一下午...... 还是要细心啊! 结 ...

  6. HDU 3966 & POJ 3237 & HYSBZ 2243 & HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  7. hysbz 2243 染色(树链剖分)

    题目链接:hysbz 2243 染色 题目大意:略. 解题思路:树链剖分+线段树的区间合并,可是区间合并比較简单,节点仅仅要记录左右端点的颜色就可以. #include <cstdio> ...

  8. BZOJ 2243: [SDOI2011]染色 [树链剖分]

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6651  Solved: 2432[Submit][Status ...

  9. bzoj-2243 2243: [SDOI2011]染色(树链剖分)

    题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6267  Solved: 2291 Descript ...

随机推荐

  1. MFC用GDI+动感歌词的制作

    源代码:http://download.csdn.net/detail/nuptboyzhb/4219669 源代码: 1.       插入一个对话框的资源,删除默认控件,并为对话框创建一个类,命名 ...

  2. 九度OnlineJudge之1018:统计同成绩学生人数

    题目描述: 读入N名学生的成绩,将获得某一给定分数的学生人数输出. 输入:                        测试输入包含若干测试用例,每个测试用例的格式为 第1行:N 第2行:N名学生的 ...

  3. MSSQL - 自增1的标识列一次增长了1000

    @情若天_RunUp: 1. Open "SQL Server Configuration Manager"2. Click "SQL Server Services&q ...

  4. JDK 安装以及环境变量的配置(Windows)

    首先下载对应版本的jdk ,然后安装,这里使用的是jdk 1.7的安装的 这个时候,JDK 已经安装完成,打开cmd 输入 java -version 就可以查看到,当前JDK 的版本如图 JDK 安 ...

  5. Boost Thread学习笔记四

    barrierbarrier类的接口定义如下:  1 class barrier : private boost::noncopyable   // Exposition only 2 { 3 pub ...

  6. [置顶] Codeforces 70D 动态凸包 (极角排序 or 水平序)

    题目链接:http://codeforces.com/problemset/problem/70/D 本题关键:在log(n)的复杂度内判断点在凸包 或 把点插入凸包 判断:平衡树log(n)内选出点 ...

  7. POJ 3619 Speed Reading(简单题)

    [题意简述]:有K头牛,N页书,每次第i头牛每分钟仅仅能读Si页书,连续读Ti分钟,之后歇息Ri分钟.如今问我们第i头牛花费多少时间能够读完这N页书. [分析]:简单的模拟 //220K 32Ms # ...

  8. 移动开发的框架(用Firepower,不用listview,超快) good

    我是通过http传送xml后台是阿帕奇的http server,后台可以用delphi或php 都可以.用post 刚才试了试自带的TNetHttpClient,感觉还好,代码封装也不算深,收发数据也 ...

  9. 与众不同 windows phone (2) - Control(控件)

    原文:与众不同 windows phone (2) - Control(控件) [索引页][源码下载] 与众不同 windows phone (2) - Control(控件) 作者:webabcd介 ...

  10. 枚举算法总结 coming~^.*

    感谢CJ同学监督╭(╯^╰)╮.从放假到现在都木有更新博客了~噶呜~小娘谨记教诲,每天会更新博客==!! 看了一下POJ训练计划,虽然已经零零散散做了40多道题了,还是从头开始整理一下漏掉的知识点.T ...