BZOJ 2243 [SDOI2011]染色:树剖【维护路径上颜色段】
题目链接: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]染色:树剖【维护路径上颜色段】的更多相关文章
- BZOJ 2243: [SDOI2011]染色 (树剖+线段树)
树链剖分后两个区间合并的时候就判一下相交颜色是否相同来算颜色段数就行了. CODE #include <vector> #include <queue> #include &l ...
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并
2243: [SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数 ...
- BZOJ 2243 [SDOI2011]染色 (树链剖分)(线段树区间修改)
[SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6870 Solved: 2546[Submit][Status][Disc ...
- [bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- BZOJ 2243: [SDOI2011]染色 (树链剖分+线段树合并)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分的点剖分+线段树.漏了一个小地方,调了一下午...... 还是要细心啊! 结 ...
- bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4637 Solved: 1726[Submit][Status ...
随机推荐
- Spring Boot内嵌Tomcat session超时问题
最近让Spring Boot内嵌Tomcat的session超时问题给坑了一把. 在应用中需要设置session超时时间,然后就习惯的在application.properties配置文件中设置如下, ...
- 【Python web自动化】之读取配置文件参数,利用cookie返回值进行跳过验证码进行登录操作
当进行Python的Web自动化时,会涉及到验证码问题,该如何跳过执行呢,下面请看代码: 1.首先新建配置文件*.ini格式 config.ini [db] #基础地址: baseurl = http ...
- (转) 对svn分支合并类型和深度的理解
合并的工作是把主干或者分支上合并范围内的所有改动列出,并对比当前工作副本的内容,由合并者手工修改冲突,然后提交到服务器的相应目录里.如果当前工作副本是主干,则合并的范围是分支上的改动,如果工作副本是分 ...
- centos7.0 安装pdo_mysql扩展
1:进入到源码包 /usr/local/php-7.1.6/ext/pdo_mysql 执行/usr/local/php-7.1/bin/phpize 如果报如下错误: Cannot find aut ...
- uiwebview 屏幕自适应 -- 根据 内容适应或者 webview适应
#import <UIKit/UIKit.h> @interface ViewController : UIViewController<UIWebViewDelegate,UISe ...
- 用象棋的思维趣说IT人的职业发展和钱途
最近我花了不少功夫在学习象棋,也学习了王天一等高手的棋路,感觉IT人的职业和下棋一样,往好了讲,争主动权争实惠只争朝夕,往坏了讲,一步走错得用多步来弥补,如果错误太大未必能弥补回来.在本文里,就用下棋 ...
- SET IDENTITY_INSERT ON/OFF 权限
今天突然遇到了,找不到对象“XXXX”,因为它不存在或者没有您所需的权限,于是检查程序,突然发现程序中有一段代码是: SET IDENTITY_INSERT eticket ON //执行业务 ... ...
- 【BZOJ2407/4398】探险/福慧双修 最短路建模
[BZOJ2407]探险 Description 探险家小T好高兴!X国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品哦!小T虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过! 比赛即将开始,工作 ...
- Hive高级
HiveServer2 概述: https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Overview2 客户端: https:// ...
- Ogbect对象转换为泛型对象
相信很多人都自己写个这个转换的方法,再次附上我自己的写转换方法仅供参考. T t = BeanUtil.dbObject2Bean(obj, tClass); public static <T& ...