2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 9012  Solved: 3375
[Submit][Status][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,表示x和y之间有一条无向边。

下面 行每行描述一个操作:

“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

第一轮day1

树链剖分+线段树
操作还是常规的区间修改 但是要注意区间合并的时候,颜色段数量的合并
在树的路径上合并区间时,有点不好处理区间左右端点,于
是我们把u->v拆成u->lca lca->v
这样区间更新端点就是同向的,即每次查询可以把一端统一地作为更新端点
由于u->lca lca->v左右端点必定重合 所以 最后答案减一

sb的我update忘了pushup调了1h

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ls u<<1
#define rs ls|1
#define ll long long
#define N 100050
using namespace std;
int n,m,tot,cnt,a[N],fa[N][20],tp[N],siz[N],hd[N];
int dep[N],tid[N],son[N],v[N];
struct edge{int v,next;}e[N<<1];
struct node{int l,r,sum,lz;}t[N<<2];
void adde(int u,int v){
e[++tot].v=v;
e[tot].next=hd[u];
hd[u]=tot;
}
void dfs1(int u,int pre){
dep[u]=dep[pre]+1;fa[u][0]=pre;siz[u]=1;
for(int j=1;(1<<j)<dep[u];j++)
fa[u][j]=fa[fa[u][j-1]][j-1];
for(int i=hd[u];i;i=e[i].next){
int v=e[i].v;
if(v==pre)continue;
dfs1(v,u);siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int anc){
if(!u)return;
tid[u]=++cnt;v[cnt]=a[u];tp[u]=anc;
dfs2(son[u],anc);
for(int i=hd[u];i;i=e[i].next){
int v=e[i].v;
if(v==fa[u][0]||v==son[u])continue;
dfs2(v,v);
}
}
int lca(int x,int y){
if(x==y)return x;
if(dep[x]<dep[y])swap(x,y);
for(int i=18;~i;i--)
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=18;~i;i--){
if(fa[x][i]==fa[y][i])continue;
x=fa[x][i];y=fa[y][i];
}
return fa[x][0];
} void pushup(int u){
t[u].sum=t[ls].sum+t[rs].sum;
t[u].l=t[ls].l;t[u].r=t[rs].r;
if(t[ls].r==t[rs].l)t[u].sum--;
}
void pushdown(int u){
if(t[u].lz==-1)return;
t[ls].l=t[ls].r=t[ls].lz=t[u].lz;
t[rs].l=t[rs].r=t[rs].lz=t[u].lz;
t[ls].sum=t[rs].sum=1;
t[u].lz=-1;
}
void build(int u,int l,int r){
t[u].lz=-1;
if(l==r){
t[u].l=t[u].r=v[l];
t[u].sum=1;return;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(u);
}
node query(int u,int L,int R,int l,int r){
if(l<=L&&R<=r)return t[u];
pushdown(u);node ret;
int mid=L+R>>1,fg=0;
if(l<=mid)ret=query(ls,L,mid,l,r),fg=1;
if(r>mid){
node tmp=query(rs,mid+1,R,l,r);
if(!fg)ret=tmp;
else{
ret.sum+=tmp.sum;
if(ret.r==tmp.l)ret.sum--;
ret.r=tmp.r;
}
}
return ret;
}
void update(int u,int L,int R,int l,int r,int c){
if(l<=L&&R<=r){
t[u].lz=t[u].l=t[u].r=c;
t[u].sum=1;return;
}
pushdown(u);
int mid=L+R>>1;
if(l<=mid)update(ls,L,mid,l,r,c);
if(r>mid)update(rs,mid+1,R,l,r,c);
pushup(u);
}
node jump(int x,int y,int val,int op){
int fx=tp[x],fy=tp[y];node ret;
ret.l=ret.r=ret.sum=0;
while(fx!=fy){
if(op)update(1,1,cnt,tid[fx],tid[x],val);
else{
node tmp=query(1,1,cnt,tid[fx],tid[x]);
ret.sum+=tmp.sum;
if(tmp.r==ret.l)ret.sum--;
ret.l=tmp.l;
}
x=fa[fx][0];fx=tp[x];
}
if(dep[x]>dep[y])swap(x,y);
if(op)update(1,1,cnt,tid[x],tid[y],val);
else{
node tmp=query(1,1,cnt,tid[x],tid[y]);
ret.sum+=tmp.sum;
if(tmp.r==ret.l)ret.sum--;
ret.l=tmp.l;
}
return ret;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
adde(a,b);adde(b,a);
}
dfs1(1,0);dfs2(1,1);
build(1,1,cnt);
int x,y,c;char s[2];
while(m--){
scanf("%s%d%d",s,&x,&y);
int anc=lca(x,y);
if(s[0]=='C'){
scanf("%d",&c);
jump(x,anc,c,1);
jump(y,anc,c,1);
}
else{
node t1,t2;
t1=jump(x,anc,0,0);
t2=jump(y,anc,0,0);
printf("%d\n",t1.sum+t2.sum-1);
}
}
return 0;
}

bzoj2243[SDOI2011]染色 树链剖分+线段树的更多相关文章

  1. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

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

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

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

  3. B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

  4. 2243: [SDOI2011]染色 树链剖分+线段树染色

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

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  7. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  8. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  9. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

随机推荐

  1. 算法第四版 coursera公开课 普林斯顿算法 ⅠⅡ部分 Robert Sedgewick主讲《Algorithms》

    这是我在网上找到的资源,下载之后上传到我的百度网盘了. 包含两部分:1:算法视频的种子 2:字幕 下载之后,请用迅雷播放器打开,因为迅雷可以直接在线搜索字幕. 如果以下链接失效,请在下边留言,我再更新 ...

  2. 深入分析Java Web中的编码问题

    编码问题一直困扰着我,每次遇到乱码或者编码问题,网上一查,问题解决了,但是实际的原理并没有搞懂,每次遇到,都是什么头疼. 决定彻彻底底的一次性解决编码问题. 1.为什么要编码 计算机的基本单元是字节, ...

  3. bzoj 4373 算术天才⑨与等差数列

    4373: 算术天才⑨与等差数列 Time Limit: 10 Sec  Memory Limit: 128 MBhttp://www.lydsy.com/JudgeOnline/problem.ph ...

  4. Scala 操作符与提取器

    实际上Scala没有操作符, 只是以操作符的格式使用方法. 操作符的优先级取决于第一个字符(除了赋值操作符), 而结合性取决于最后一个字符 Scala的操作符命名更加灵活:) 操作符 中置操作符(In ...

  5. zookeeper安装及环境变量设置

    下载 首先去官网下载(自行选择版本):http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.11/然后执行tar -zxvf解压 对于后台安装 ...

  6. “认证发布”和“获取展示”,如何在 SharePoint 中正确使用 RSS Feed。

    在我们进行的日常工作中,是由一部分信息需要 Share 给其他人或者组织的.SharePoint 虽然支持在某个 Site Collection 中互通信息,但是跨 Site Collection 的 ...

  7. 新概念英语(1-139)Is that you, John?

    Lesson 139 Is that you, John? 是你吗,约翰? Listen to the tape then answer this question. Which John Smith ...

  8. Linux背景知识(1)RedHat和Centos

    Redhat有收费的商业版和免费的开源版,商业版的业内称之为RHEL(Red Hat Enterprise Linux)系列, 而这个CentOS(Community ENTerprise Opera ...

  9. Angular 学习笔记 ( CDK - Layout )

    简单说就是 js 的 media query. 1. BreakpointObserver  const layoutChanges = this.breakpointObserver.observe ...

  10. Python的下载及安装

    1.官网下载地址:https://www.python.org/downloads/ 2.python设置环境变量: 在系统变量里添加Python的安装位置 3.在cmd里输入python里即可