题目链接: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执行性能关注点

    繁琐复杂的执行计划.可能迷了开发人员的眼.导致一条性感又傻X的SQL 在服务器上跑得特欢乐     有介于此.重点抓住几个部分.至于其他的嘛.当然是.非礼勿视咯..          ㈠ 返回行的数量 ...

  2. 详细的obs操作教程(windows/mac)图解

    直播推流软件obs操作配置教程包含支持mac和windows配置 1 2 3 4 5 6 7 8 9

  3. openWRT自学计划安排

    目标:充分理解openwrt的框架构成,能够在openwrt框架下实现:开发新程序,修改现有程序,修改内核,修改boot.为此,制定如下计划: 一.如何在openwrt上做开发 1.编译出一个BRCM ...

  4. eclipse配置jp.gr.java_conf.ussiy.app.propedit_5.3.3

    配置PropertiesEditor插件 jp.gr.java_conf.ussiy.app.propedit_5.3.3   1.下载PropertiesEditor插件 http://pan.ba ...

  5. 【Python + Selenium】之unittest测试用例满足条件,进行跳过测试Skip

    直接上代码: __author__ = 'zc' import unittest class demoSkipTest(unittest.TestCase): a = 70 b = 50 print( ...

  6. sql with 递归查询

    用with实现递归查询 1.数据准备 假定有一个表DiGui,有两个字段Id int ParentId int Id ParentId 4 0 5 0 7 0 2 1 8 5 15 5 9 7 14 ...

  7. iOS_3_图片浏览

    终于效果图: BeyondViewController.h // // BeyondViewController.h // 03_图片浏览 // // Created by beyond on 14- ...

  8. 研究怎么运用xcode处理常见的调试问题

    本文转载至 http://blog.csdn.net/zhuzhihai1988/article/details/7749022 所谓磨刀不误砍柴工,这里菜鸟我在研究怎么运用xcode处理常见的调试问 ...

  9. spring工作原理理解

    spring的工作原理 spring是作为一个容器存在的框架,可以加载spring web,spring mvc,spring orm,sprong aop,spring dao等框架和模块,其主要核 ...

  10. HYSBZ - 1799 self 同类分布

    self 同类分布 HYSBZ - 1799 给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数.Sample Input 10 19 Sample Output 3 Hint [约束条件] ...