染色 SDOI2011

染色 SDOI2011

描述:
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。

输入:
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面n-1行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面m行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

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

样例输入
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

样例输出
3
1
2

数据规模附上

显然,数据规模是骗人的,1<=n<=1e5才是正解哦

解题思路:
树链剖分+线段树维护。
树链部分除了查询全模板,这里不过多详述,说一下查询,查询时往上跳(意会就好)的时候需要保存下lastx和lasty。配合查询x和y查询的结果更新答案。考虑到一一对应性,交换时两组值都要交换。
线段树部分需要维护区间最左边的颜色,最右边的颜色,颜色段的个数以及一个万恶的lazy标记(代码中用cg表示)。大区间的颜色段数=左区间颜色段数+右区间颜色段数,如果左区间最右端等于右区间最左端,大区间颜色段数减一。
本题还有一大坑点,注意建树时不能把颜色更新,只更新区间标记和cg即可,同时别忘了sum归零。建树完成后再更新每个节点的值才不会把树上不同链的颜色更新在一起。
接下来也就是最最恶心的代码实现和排错了,虽然花费我半天时间,但时间也不是白费,至少我对树链剖分的运行机制和坑点有了更好的理解,嗯,下次会更好,加油!


代码附上

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define LD (o<<1)
#define RD ((o<<1)|1)
struct Tree{
    int l,r,sum;
    int lc,rc;//记录最左最右的颜色
    int cg;//记录更改
}T[4*N];//线段树
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值