题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

题意:

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

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

  2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如"112221"由3段组成:"11"、"222"和"1"。

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

题解:

  树剖。

  线段树上维护区间颜色段,每个节点:

    dat[]:当前区间的颜色段数量

    st[]:修改标记

    lc[] and rc[]:当前区间的最左端和最右端颜色

    lson[] and rson[]:左右儿子编号

  线段树部分见NOI 2007 项链工厂。

  树剖query中,每次a = par[tp[a]]往上跳之前,先判断getcol(dfsx[tp[a]]) == getcol(dfsx[par[tp[a]]])

  如果相等,上下两端合并,sum--。

AC Code:

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <vector>
#define MAX_N 1000005 using namespace std; int n,m;
int tot=;
int cnt=;
int c[MAX_N];
int dat[MAX_N];
int st[MAX_N];
int lc[MAX_N];
int rc[MAX_N];
int lson[MAX_N];
int rson[MAX_N];
int par[MAX_N];
int dep[MAX_N];
int siz[MAX_N];
int tp[MAX_N];
int son[MAX_N];
int dfsx[MAX_N];
int idx[MAX_N];
vector<int> edge[MAX_N]; void read()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&c[i]);
}
int a,b;
for(int i=;i<n;i++)
{
scanf("%d%d",&a,&b);
edge[a].push_back(b);
edge[b].push_back(a);
}
} void push_down(int now)
{
if(st[now]!=-)
{
dat[lson[now]]=dat[rson[now]]=;
st[lson[now]]=st[rson[now]]=st[now];
lc[lson[now]]=rc[lson[now]]=lc[rson[now]]=rc[rson[now]]=st[now];
st[now]=-;
}
} void push_up(int now)
{
dat[now]=;
lc[now]=lc[lson[now]];
rc[now]=rc[rson[now]];
if(lson[now]) dat[now]+=dat[lson[now]];
if(rson[now]) dat[now]+=dat[rson[now]];
if(lson[now] && rson[now] && rc[lson[now]]==lc[rson[now]]) dat[now]--;
} int build(int l,int r)
{
int rt=++tot;
dat[rt]=;
st[rt]=-;
lc[rt]=c[idx[l]];
rc[rt]=c[idx[r]];
lson[rt]=rson[rt]=;
if(l<r)
{
int mid=(l+r)>>;
lson[rt]=build(l,mid);
rson[rt]=build(mid+,r);
push_up(rt);
}
return rt;
} void update(int a,int b,int k,int l,int r,int x)
{
if(a<=l && r<=b)
{
dat[k]=;
st[k]=lc[k]=rc[k]=x;
return;
}
if(r<a || b<l) return;
push_down(k);
int mid=(l+r)>>;
update(a,b,lson[k],l,mid,x);
update(a,b,rson[k],mid+,r,x);
push_up(k);
} int query(int a,int b,int k,int l,int r)
{
if(a<=l && r<=b) return dat[k];
if(r<a || b<l) return ;
push_down(k);
int mid=(l+r)>>;
int ans=;
if(a<=mid) ans+=query(a,b,lson[k],l,mid);
if(b>mid) ans+=query(a,b,rson[k],mid+,r);
if(a<=mid && b>mid && rc[lson[k]]==lc[rson[k]]) ans--;
return ans;
} int getcol(int p,int k,int l,int r)
{
if(l==r) return lc[k];
push_down(k);
int mid=(l+r)>>;
if(p<=mid) return getcol(p,lson[k],l,mid);
else return getcol(p,rson[k],mid+,r);
} void dfs1(int now,int p,int d)
{
par[now]=p;
dep[now]=d;
siz[now]=;
for(int i=;i<edge[now].size();i++)
{
int temp=edge[now][i];
if(temp!=p)
{
dfs1(temp,now,d+);
siz[now]+=siz[temp];
}
}
} void dfs2(int now,int anc)
{
tp[now]=anc;
son[now]=-;
cnt++;
idx[cnt]=now;
dfsx[now]=cnt;
for(int i=;i<edge[now].size();i++)
{
int temp=edge[now][i];
if((son[now]==- || siz[temp]>siz[son[now]]) && temp!=par[now])
{
son[now]=temp;
}
}
if(son[now]!=-) dfs2(son[now],anc);
for(int i=;i<edge[now].size();i++)
{
int temp=edge[now][i];
if(temp!=par[now] && temp!=son[now]) dfs2(temp,temp);
}
} void update_chain(int a,int b,int x)
{
while(tp[a]!=tp[b])
{
if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
update(dfsx[tp[a]],dfsx[a],,,n,x);
a=par[tp[a]];
}
if(dep[a]<dep[b]) swap(a,b);
update(dfsx[b],dfsx[a],,,n,x);
} int query_chain(int a,int b)
{
int sum=;
while(tp[a]!=tp[b])
{
if(dep[tp[a]]<dep[tp[b]]) swap(a,b);
sum+=query(dfsx[tp[a]],dfsx[a],,,n);
if(getcol(dfsx[tp[a]],,,n)==getcol(dfsx[par[tp[a]]],,,n)) sum--;
a=par[tp[a]];
}
if(dep[a]<dep[b]) swap(a,b);
sum+=query(dfsx[b],dfsx[a],,,n);
return sum;
} void work()
{
dfs1(,-,);
dfs2(,);
build(,n);
char s[];
int a,b,c;
while(m--)
{
scanf("%s",s);
if(s[]=='Q')
{
scanf("%d%d",&a,&b);
printf("%d\n",query_chain(a,b));
}
else
{
scanf("%d%d%d",&a,&b,&c);
update_chain(a,b,c);
}
}
} int main()
{
read();
work();
}

BZOJ 2243 [SDOI2011]染色:树剖【维护路径上颜色段】的更多相关文章

  1. BZOJ 2243: [SDOI2011]染色 (树剖+线段树)

    树链剖分后两个区间合并的时候就判一下相交颜色是否相同来算颜色段数就行了. CODE #include <vector> #include <queue> #include &l ...

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

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

  3. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

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

  4. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

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

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

  6. BZOJ 2243 [SDOI2011]染色 (树链剖分)(线段树区间修改)

    [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6870  Solved: 2546[Submit][Status][Disc ...

  7. [bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]

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

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

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

  9. bzoj 2243 [SDOI2011]染色(树链剖分,线段树)

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

随机推荐

  1. oracle高性能的SQL语句的写法

    1.当多表查询的时候,把数据量小的表放在最后面,ORACLE会把最后面的表当作基础表,因为表间连接时,最右边的表会被放到嵌套循环的最外层.最外层的循环次数越少,效率越高. 2.Oracle采用自下而上 ...

  2. 改进Spring中的分页技术

    Spring中有一个PagedListHolder,能够实现分页. 但此类有几个缺点: 1. 使用此类的代码比較繁琐 2. 此类存放的数据源是全部的记录集,即对于记录数为1000条的数据,即使我们仅仅 ...

  3. Unity3D研究院之在开始学习拓展编辑器

    Unity拥有非常丰富的拓展编辑器接口,如果是在网上下载过别人写的插件,你会发现为什么它的监测面板视图和普通的不一样?其实是他通过代码自己绘制的监测面板,这篇博文MOMO带大家来学习编辑器.如下图所示 ...

  4. poj2891(线性同余方程组)

    一个exgcd解决一个线性同余问题,多个exgcd解决线性同余方程组. Strange Way to Express Integers Time Limit: 1000MS   Memory Limi ...

  5. SDOI 2016 Round1 Day1

    储能表 /* 引自zyz大佬的数学思想 */ #include<cstdio> #include<iostream> using namespace std; typedef ...

  6. EasyNVR无插件直播服务器播放页面的集成----单独的播放器样式

    背景需求: EasyNVR自身拥有独立的客户端体系,安卓和IOS拥有各自独立的APP, 安卓下载地址:https://fir.im/EasyNVR: IOS下载可直接在APPstore搜索EasyNV ...

  7. java拾遗2----XML解析(二) SAX解析

    XML解析之SAX解析: SAX解析器:SAXParser类同DOM一样也在javax.xml.parsers包下,此类的实例可以从 SAXParserFactory.newSAXParser() 方 ...

  8. 【Emit】关于System.MethodAccessException解决方案

        最近学习Emit,在使用Emit动态生成对象时碰到一些"蛋疼"的问题,如下: 1.安全透明方法"XXX.XX()"尝试访问安全关键方法"YYY ...

  9. 九度OJ 1002:Grading

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:18410 解决:4753 题目描述: Grading hundreds of thousands of Graduate Entrance ...

  10. jvm的字符串池

    1 jvm中是有专门的字符串池的内存空间的,这块空间和栈和堆不同. 2 String s = "string constant"; 这个时候,如果string pool中没有&qu ...