2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB

Submit: 4537  Solved: 1702

[

id=2243" style="color:blue; text-decoration:none">Submit][Status][

id=2243" style="color:blue; text-decoration:none">Discuss]

Description

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

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

2、询问节点a到节点b路径上的颜色段数量(连续同样颜色被觉得是同一段)。如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完毕这m个操作。

Input

第一行包括2个整数n和m,分别表示节点数和操作数;

第二行包括n个正整数表示n个节点的初始颜色

以下 行每行包括两个整数x和y,表示xy之间有一条无向边。

以下 行每行描写叙述一个操作:

“C a b c”表示这是一个染色操作。把节点a到节点b路径上全部点(包含a和b)都染成颜色c;

“Q a b”表示这是一个询问操作。询问节点a到节点b(包含a和b)路径上的颜色段数量。

Output

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

Sample Input

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


Sample Output

3



1



2

HINT

数N<=10^5。操作数M<=10^5,全部的颜色C为整数且在[0, 10^9]之间。

Source

有关链的操作,非常显然树链剖分+线段树维护区间。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 100005
using namespace std;
struct seg{int l,r,lc,rc,s,tag;}t[maxn*4];
struct edge_type{int next,to;}e[maxn*2];
int n,m,x,y,z,cnt,tot;
int head[maxn],d[maxn],son[maxn],belong[maxn],p[maxn],a[maxn],f[maxn][18];
char ch;
bool vst[maxn];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void add_edge(int x,int y)
{
e[++cnt]=(edge_type){head[x],y};head[x]=cnt;
e[++cnt]=(edge_type){head[y],x};head[y]=cnt;
}
inline void dfs1(int x)
{
vst[x]=true;son[x]=1;
for(int i=1;i<=17;i++)
{
if (d[x]<(1<<i)) break;
f[x][i]=f[f[x][i-1]][i-1];
}
for(int i=head[x];i;i=e[i].next)
{
if (vst[e[i].to]) continue;
d[e[i].to]=d[x]+1;
f[e[i].to][0]=x;
dfs1(e[i].to);
son[x]+=son[e[i].to];
}
}
inline void dfs2(int x,int chain)
{
p[x]=++tot;belong[x]=chain;
int k=0;
for(int i=head[x];i;i=e[i].next)
if (d[e[i].to]>d[x]&&son[k]<son[e[i].to]) k=e[i].to;
if (!k) return;
dfs2(k,chain);
for(int i=head[x];i;i=e[i].next)
if (d[e[i].to]>d[x]&&e[i].to!=k) dfs2(e[i].to,e[i].to);
}
inline int lca(int x,int y)
{
if (d[x]<d[y]) swap(x,y);
int t=d[x]-d[y];
F(i,0,17) if (t&(1<<i)) x=f[x][i];
if (x==y) return x;
D(i,17,0) if (f[x][i]!=f[y][i]){x=f[x][i];y=f[y][i];}
return f[x][0];
}
inline void build(int k,int l,int r)
{
t[k].l=l;t[k].r=r;t[k].s=1;t[k].tag=-1;
if (l==r) return;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
inline void pushup(int k)
{
t[k].lc=t[k<<1].lc;t[k].rc=t[k<<1|1].rc;
if (t[k<<1].rc==t[k<<1|1].lc) t[k].s=t[k<<1].s+t[k<<1|1].s-1;
else t[k].s=t[k<<1].s+t[k<<1|1].s;
}
inline void update(int k,int z)
{
t[k].tag=t[k].lc=t[k].rc=z;
t[k].s=1;
}
inline void pushdown(int k)
{
if (t[k].tag==-1) return;
update(k<<1,t[k].tag);
update(k<<1|1,t[k].tag);
t[k].tag=-1;
}
inline void change(int k,int l,int r,int x)
{
if (t[k].l==l&&t[k].r==r){update(k,x);return;}
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if (r<=mid) change(k<<1,l,r,x);
else if (l>mid) change(k<<1|1,l,r,x);
else{change(k<<1,l,mid,x);change(k<<1|1,mid+1,r,x);}
pushup(k);
}
inline int ask(int k,int l,int r)
{
if (t[k].l==l&&t[k].r==r) return t[k].s;
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if (r<=mid) return ask(k<<1,l,r);
else if (l>mid) return ask(k<<1|1,l,r);
else
{
int tmp=t[k<<1].rc==t[k<<1|1].lc;
return ask(k<<1,l,mid)+ask(k<<1|1,mid+1,r)-tmp;
}
}
inline int getc(int k,int pos)
{
if (t[k].l==t[k].r) return t[k].lc;
pushdown(k);
int mid=(t[k].l+t[k].r)>>1;
if (pos<=mid) return getc(k<<1,pos);
else return getc(k<<1|1,pos);
}
inline void solvechange(int x,int t,int c)
{
while (belong[x]!=belong[t])
{
change(1,p[belong[x]],p[x],c);
x=f[belong[x]][0];
}
change(1,p[t],p[x],c);
}
inline int solvesum(int x,int t)
{
int sum=0;
while (belong[x]!=belong[t])
{
sum+=ask(1,p[belong[x]],p[x]);
if (getc(1,p[belong[x]])==getc(1,p[f[belong[x]][0]])) sum--;
x=f[belong[x]][0];
}
sum+=ask(1,p[t],p[x]);
return sum;
}
int main()
{
n=read();m=read();
F(i,1,n) a[i]=read();
F(i,1,n-1){x=read();y=read();add_edge(x,y);}
dfs1(1);
dfs2(1,1);
build(1,1,n);
F(i,1,n) change(1,p[i],p[i],a[i]);
F(i,1,m)
{
ch=getchar();
while (ch<'A'||ch>'Z') ch=getchar();
if (ch=='Q')
{
x=read();y=read();
int t=lca(x,y);
printf("%d\n",solvesum(x,t)+solvesum(y,t)-1);
}
else
{
x=read();y=read();z=read();
int t=lca(x,y);
solvechange(x,t,z);solvechange(y,t,z);
}
}
}

bzoj2243【SDOI2011】染色的更多相关文章

  1. BZOJ2243 SDOI2011 染色 【树链剖分】

    BZOJ2243 SDOI2011 染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色 ...

  2. bzoj2243[SDOI2011]染色 树链剖分+线段树

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

  3. [bzoj2243][SDOI2011]染色

    Description 给定一棵有$n$个节点的无根树和$m$个操作,操作有$2$类: 1.将节点$a$到节点$b$路径上所有点都染成颜色$c$; 2.询问节点$a$到节点$b$路径上的颜色段数量(连 ...

  4. BZOJ2243[SDOI2011]染色——树链剖分+线段树

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

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

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

  6. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  7. BZOJ2243: [SDOI2011]染色(树链剖分/LCT)

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

  8. bzoj2243: [SDOI2011]染色--线段树+树链剖分

    此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...

  9. BZOJ2243——[SDOI2011]染色

    1.题目大意:给个树,然后树上每个点都有颜色,然后会有路径的修改,有个询问,询问一条路径上的颜色分成了几段 2.分析:首先这个修改是树剖可以做的,对吧,但是这个分成了几段怎么搞呢,我们的树剖的不是要建 ...

  10. bzoj2243 sdoi2011 染色 paint

    明明是裸树剖 竟然调了这么久好蛋疼 大概是自己比较水的原因吧 顺便+fastio来gangbang #include<iostream> #include<cstring> # ...

随机推荐

  1. Angular——内置服务

    $location <!DOCTYPE html> <html lang="en" ng-app="App"> <head> ...

  2. c3p0参数详解

    <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数.Default: 3 --> <property name="acquireIncrement"& ...

  3. spring源码下载链接

    http://www.blogjava.net/zhyiwww/archive/2014/10/17/418809.html

  4. 洛谷——P3373 【模板】线段树 2&& B 数据结构

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

  5. Linux学习笔记(二) 文件管理

    了解 Linux 系统基本的文件管理命令可以帮助我们更好的使用 Linux 系统,以下介绍几个常用的文件管理命令 1.pwd pwd 是 Print Working Directory 的简写,用于显 ...

  6. OpenCV+Python识别车牌和字符分割的实现

    本篇文章主要基于python语言和OpenCV库(cv2)进行车牌区域识别和字符分割,开篇之前针对在python中安装opencv的环境这里不做介绍,可以自行安装配置! 车牌号检测需要大致分为四个部分 ...

  7. 洛谷 1541 NOIp2010提高组 乌龟棋

    [题解] 很容易想到这是一个DP,f[i][j][k][l]表示4种卡片分别用了多少张,那么转移方程就是f[i][j][k][l]=Max(f[i-1][j][k][l],f[i][j-1][k][l ...

  8. [模拟赛FJOI Easy Round #2][T3 skill] (最小割+最大权闭合子图(文理分科模型))

    [题目描述] 天上红绯在游戏中扮演敏剑,对于高攻击低防御的职业来说,爆发力显得非常重要,为此,她准备学习n个技能,每个技能都有2个学习方向:物理攻击和魔法攻击.对于第i个技能,如果选择物理攻击方向,会 ...

  9. maven profile多环境自动切换配置,配置分离,排除文件

    痛点: 在java开发的过程中,我们经常要面对各种各样的环境,比如开发环境,测试环境,正式环境,而这些环境对项目的需求也不相同. 在此之前,我们往往需要手动去修改相对应的配置文件然后打成war,才能部 ...

  10. https://blog.csdn.net/u011495642/article/details/79958444

    https://blog.csdn.net/u011495642/article/details/79958444--- 一文读懂大数据平台——写给大数据开发初学者的话! 史上最详细的Hadoop环境 ...