传送门

【题目分析】

果然重构才是真理吗。。。。。

因为涉及路径操作,所以考虑树链剖分,线段树维护题意中的:

1.区间颜色段数。

2.区间左右颜色。

3.区间覆盖标记。

因为线段树的问题主要就是考虑push_up和push_down,此题push_up时记得将区间左右颜色赋值,然后合并的时候注意如果左区间右端颜色与右区间左端颜色相同的话那么颜色段数要-1,push_down时如果有区间覆盖标记,就将整段区间的颜色赋值为修改颜色,颜色段数为1,记得下传。

然后就是路径修改询问,修改常规,询问的时候因为要将一段一段的路径拼起来,所以要检查每接一段的交界处的颜色是否一样。

细节稍多(重载运算符的时候忘return了。。好窒息)

【代码~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
const int MAXM=2e5+10;int n,q,cnt;
int a[MAXN];
int head[MAXN],depth[MAXN],fa[MAXN],son[MAXN],siz[MAXN],top[MAXN];
int nxt[MAXM],to[MAXM];
int dfn[MAXN],ys[MAXN],tot;
struct Tree{int l,r;int cnt;int lc,rc;int cov;friend inline Tree operator+(const Tree &a,const Tree &b){Tree c;c.l=a.l,c.r=b.r;c.cnt=a.cnt+b.cnt;if(a.rc==b.lc)c.cnt--;c.lc=a.lc,c.rc=b.rc;return c;}
}tr[MAXN<<2];int Read(){int i=0,f=1;char c;for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());if(c=='-')f=-1,c=getchar();for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';return i*f;
}void add(int x,int y){nxt[cnt]=head[x];head[x]=cnt;to[cnt]=y;cnt++;
}void dfs1(int u,int f){siz[u]=1;for(int i=head[u];i!=-1;i=nxt[i]){int v=to[i];if(v==f)continue;fa[v]=u;depth[v]=depth[u]+1;dfs1(v,u);siz[u]+=siz[v];if(siz[v]>siz[son[u]])son[u]=v;}
}void dfs2(int u,int tp){top[u]=tp;dfn[u]=++tot;ys[tot]=u;if(!son[u])return ;dfs2(son[u],tp);for(int i=head[u];i!=-1;i=nxt[i]){int v=to[i];if(v==fa[u]||v==son[u])continue;dfs2(v,v);}
}void push_up(int root){tr[root].cnt=tr[root<<1].cnt+tr[root<<1|1].cnt;if(tr[root<<1].rc==tr[root<<1|1].lc)tr[root].cnt--;tr[root].lc=tr[root<<1].lc;tr[root].rc=tr[root<<1|1].rc;
}void push_now(int root,int col){tr[root].cnt=1;tr[root].lc=tr[root].rc=col;tr[root].cov=col;
}void push_down(int root){if(tr[root].cov!=-1){push_now(root<<1,tr[root].cov);push_now(root<<1|1,tr[root].cov);tr[root].cov=-1;}
}void build(int root,int l,int r){tr[root].l=l,tr[root].r=r;tr[root].cov=-1;if(l==r){tr[root].cnt=1;tr[root].lc=tr[root].rc=a[ys[l]];return ;}int mid=l+r>>1;build(root<<1,l,mid);build(root<<1|1,mid+1,r);push_up(root);
}void update(int root,int l,int r,int L,int R,int key){if(l>R||r<L)return ;if(L<=l&&r<=R){push_now(root,key);return ;}push_down(root);int mid=l+r>>1;if(R<=mid)update(root<<1,l,mid,L,R,key);else{if(L>mid)update(root<<1|1,mid+1,r,L,R,key);elseupdate(root<<1,l,mid,L,mid,key),update(root<<1|1,mid+1,r,mid+1,R,key);}push_up(root);
}Tree query(int root,int l,int r,int L,int R){if(L<=l&&r<=R){return tr[root];}push_down(root);int mid=l+r>>1;if(R<=mid)return query(root<<1,l,mid,L,R);else{if(L>mid)return query(root<<1|1,mid+1,r,L,R);else{Tree tr1=query(root<<1,l,mid,L,mid);Tree tr2=query(root<<1|1,mid+1,r,mid+1,R);return tr1+tr2;}}
}void update_path(int x,int y,int key){while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]])swap(x,y);update(1,1,n,dfn[top[x]],dfn[x],key);x=fa[top[x]];}if(depth[x]<depth[y])swap(x,y);update(1,1,n,dfn[y],dfn[x],key);
}int query_path(int x,int y){int ret=0,lc=0,rc=0;Tree ans;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]])swap(x,y),swap(lc,rc);ans=query(1,1,n,dfn[top[x]],dfn[x]);ret+=ans.cnt;if(ans.rc==lc)ret--;lc=ans.lc;x=fa[top[x]];}if(depth[x]<depth[y])swap(x,y),swap(lc,rc);ans=query(1,1,n,dfn[y],dfn[x]);ret+=ans.cnt;if(ans.rc==lc)ret--;if(ans.lc==rc)ret--;return ret;
}int main(){memset(head,-1,sizeof(head));n=Read(),q=Read();for(int i=1;i<=n;++i){a[i]=Read();}for(int i=1;i<n;++i){int x=Read(),y=Read();add(x,y);add(y,x);}dfs1(1,-1);dfs2(1,1);build(1,1,n);while(q--){char cz[5];scanf("%s",cz);int l=Read(),r=Read();if(cz[0]=='C'){int k=Read();update_path(l,r,k);}elsecout<<query_path(l,r)<<'\n';}return 0;
}

转载于:https://www.cnblogs.com/Ishtar/p/10291858.html

洛谷2486 【SDOI2011】染色(线段树+树链剖分)相关推荐

  1. 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)

    [题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...

  2. 洛谷 P2486 [SDOI2011]染色 树链剖分

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...

  3. 洛谷P2495 [SDOI2011]消耗战(虚树dp)

    P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...

  4. 洛谷 P2486 [SDOI2011]染色 LCT

    Code: #include <cstdio> //SDOI2010 染色 #include <algorithm> #include <cstring> #inc ...

  5. 信息学奥赛一本通 1365:FBI树(fbi) | 1928:【04NOIP普及组】FBI树 | 洛谷 P1087 [NOIP2004 普及组] FBI 树

    [题目链接] ybt 1365:FBI树(fbi) ybt 1928:[04NOIP普及组]FBI树 洛谷 P1087 [NOIP2004 普及组] FBI 树 [题目考点] 1. 二叉树 [解题思路 ...

  6. [Luogu 2486] SDOI2011 染色

    [Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...

  7. 洛谷(P3373)线段树加乘混合模板

    题目链接:P3373 [模板]线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 这道题目的意思很明确,就是要我们在线完成区间的乘和加运算并支持查询区间和的一个问题.处理这道 ...

  8. [Bzoj2243][SDOI2011]染色(线段树树剖)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2243 线段树+树链剖分,在线段树需要每次用lt和rt两个数组记录当前区间的左右边界的颜色 ...

  9. 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)

    洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...

最新文章

  1. BestCoder Round #68 (div.2) 1002 tree
  2. 手机主宰了你的生活,这不是乔布斯想看到的
  3. Spring Boot + Elasticsearch
  4. 反手发力动作--乒在民间
  5. HTML5实践 -- 三步实现响应式设计
  6. BitAdminCore框架更新日志20180529
  7. oracle udev 多路径,Suse 11下多路径及udev配置
  8. javascript实现页面跳转的方法
  9. Android开发笔记(一百二十三)下拉刷新布局SwipeRefreshLayout
  10. 蚂蚁金服的生死时速!
  11. 如何用c语言对隐函数求导,隐函数求导的方法
  12. MC34063芯片应用
  13. 使用ListIterator 对List遍历时修改,删除
  14. 2022年 微前端技术调研- 图文并茂
  15. 避 孕药熟知的几种负面影响
  16. 国内云计算的下半场机遇在哪里?
  17. 应变/温度数据采集系统设计方案——德维创(DEWETRON)
  18. win10鼎信诺为什么安装不了_2016年鼎信诺常见问题处理.docx
  19. 定位(如何运用定位)
  20. 排序算法Python实现合辑

热门文章

  1. 数据库连接池种类及性能
  2. python编程中的if __name__ == 'main' 的作用和原理
  3. Proxy(代理,拦截器),Reflect(反射)
  4. jQuery插件开发的准备
  5. MDT2012+ADK8.0+WDS部署Windows客户端(一)部署概念和方法论
  6. [工具]将xml文件转换为html显示
  7. 鼠标点击层以外的地方层隐藏
  8. python gzip模块实现文件压缩的方法
  9. makefile how to
  10. 【iOS】Touch Drag Inside 和 Touch Drag Outside、Touch Drag Enter、Touch Drag Exit的区别