【SDOI2011】bzoj2243 染色

2023-11-07 20:38
文章标签 染色 sdoi2011 bzoj2243

本文主要是介绍【SDOI2011】bzoj2243 染色,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Description

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

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

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

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

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

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

树剖之后对线段树的每个节点记录颜色数、左端点颜色和右端点颜色,方便合并。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int fa[100010],son[100010],dep[100010],top[100010],pos[100010],size[100010],
num[1000010],tag[1000010],lc[1000010],rc[1000010],
fir[100010],ne[200010],to[200010],clr[100010],
m,n,tot;
void add(int num,int u,int v)
{ne[num]=fir[u];fir[u]=num;to[num]=v;
}
void init()
{int i,x,y;scanf("%d%d",&n,&m);for (i=1;i<=n;i++)scanf("%d",&clr[i]);for (i=1;i<n;i++){scanf("%d%d",&x,&y);add(i*2,x,y);add(i*2+1,y,x);}
}
void down(int p)
{if (tag[p]>=0){tag[p*2]=tag[p*2+1]=lc[p]=rc[p]=tag[p];num[p]=1;tag[p]=-1;}
}
void up(int p)
{down(p);down(p*2);down(p*2+1);lc[p]=lc[p*2];rc[p]=rc[p*2+1];num[p]=num[p*2]+num[p*2+1]-(bool)(rc[p*2]==lc[p*2+1]);
}
void modi(int p,int L,int R,int l,int r,int x)
{down(p);if (L==l&&R==r){tag[p]=x;return;}int mid=(L+R)/2;if (r<=mid) modi(p*2,L,mid,l,r,x);else{if (l>=mid+1) modi(p*2+1,mid+1,R,l,r,x);else{modi(p*2,L,mid,l,mid,x);modi(p*2+1,mid+1,R,mid+1,r,x);}}up(p);
}
int qry(int p,int L,int R,int l,int r,int &ll,int &rr)
{down(p);if (L==l&&R==r){ll=lc[p];rr=rc[p];return num[p];}int mid=(L+R)/2;if (r<=mid) return qry(p*2,L,mid,l,r,ll,rr);if (l>=mid+1) return qry(p*2+1,mid+1,R,l,r,ll,rr);int a1,l1,r1,a2,l2,r2;a1=qry(p*2,L,mid,l,mid,l1,r1);a2=qry(p*2+1,mid+1,R,mid+1,r,l2,r2);ll=l1;rr=r2;return a1+a2-(bool)(r1==l2);
}
void dfs1(int u,int f)
{int i,v;size[u]=1;for (i=fir[u];i;i=ne[i])if ((v=to[i])!=f){dep[v]=dep[u]+1;fa[v]=u;dfs1(v,u);size[u]+=size[v];if (son[u]==0||size[v]>size[son[u]])son[u]=v;}
}
void dfs2(int u)
{int i,v;pos[u]=++tot;if (!son[u]) return;top[son[u]]=top[u];dfs2(son[u]);for (i=fir[u];i;i=ne[i])if ((v=to[i])!=son[u]&&v!=fa[u]){top[v]=v;dfs2(v);}
}
void pre()
{int i;dep[1]=1;dfs1(1,-1);top[1]=1;dfs2(1);memset(tag,-1,sizeof(tag));for (i=1;i<=n;i++)modi(1,1,tot,pos[i],pos[i],clr[i]);
}
void modify(int u,int v,int x)
{int f1,f2;while ((f1=top[u])!=(f2=top[v])){if (dep[f1]<dep[f2]){swap(f1,f2);swap(u,v);}modi(1,1,tot,pos[f1],pos[u],x);u=fa[f1];}if (dep[u]<dep[v])swap(u,v);modi(1,1,tot,pos[v],pos[u],x);
}
int query(int u,int v)
{int l1=-1,l2=-1,ret=0,f1,f2,tl,tr,temp;while ((f1=top[u])!=(f2=top[v]))if (dep[f1]<dep[f2]){temp=qry(1,1,tot,pos[f2],pos[v],tl,tr);ret+=temp-(bool)(l2==tr);l2=tl;v=fa[f2];}else{temp=qry(1,1,tot,pos[f1],pos[u],tl,tr);ret+=temp-(bool)(l1==tr);l1=tl;u=fa[f1];}if (dep[u]<dep[v]){temp=qry(1,1,tot,pos[u],pos[v],tl,tr);ret+=temp-(bool)(l1==tl)-(bool)(l2==tr);}else{temp=qry(1,1,tot,pos[v],pos[u],tl,tr);ret+=temp-(bool)(l2==tl)-(bool)(l1==tr);}return ret;
}
int main()
{char s[5];int x,y,z;init();pre();while (m--){scanf("%s",s);if (s[0]=='C'){scanf("%d%d%d",&x,&y,&z);modify(x,y,z);}else{scanf("%d%d",&x,&y);printf("%d\n",query(x,y));}}
}

这篇关于【SDOI2011】bzoj2243 染色的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/366145

相关文章

【HDU】5574 Colorful Tree【子树染色,询问子树颜色数——线段树+bit+lca+set】

题目链接:【HDU】5574 Colorful Tree 题目大意:对一个子树染色,询问一个子树的颜色数。 题目分析: set set维护每种颜色所在的 dfs dfs序区间,修改均摊 nlogn nlogn。 #include <bits/stdc++.h>using namespace std ;typedef long long LL ;typedef pair < int , i

HDU4185Oil Skimming(行列匹配||棋盘匹配||黑白染色||1X2矩形覆盖)

题意:找出最多的形如“##”横着竖着都可以,明显的1X2矩形覆盖,直接按坐标和的奇偶来分为二分图。 #include<cstdio>#include<iostream>#include<algorithm>#include<cmath>#include<set>#include<map>#include<string>#include<cstring>#include<stac

关于二分图染色的几点总结

二分图染色的概念: 二分图染色是一种用来判断给定图(有向图或无向图)是否是二分图的算法。在图上不断进行BFS或DFS,并在运行过程中不断对结点进行"染色","染色"保证相邻结点的颜色必然不同。如果无法保证,则这个图就是二分图. 二分图染色时的注意事项: 二分图染色的题常会结合DP进行考察,因此往往要注意推理状态转移方程二分图染色类型的题目也有可能结合类似DAG上的推论这种图上定理进行考察,这

三色染色问题

三色染色问题 有排成一行的n个方格,用红、黄、绿三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色。 求全部的满足要求的涂法种数。 代码 #include<iostream>#include<cstdio>using namespace std;long long dp[100]={0,3,6,6};int main(){int n;scanf("%d"

人工智能在数字病理切片虚拟染色以及染色标准化领域的研究进展|顶刊速递·24-06-23

小罗碎碎念 本期推文主题:人工智能在数字病理切片虚拟染色以及染色标准化领域的研究进展 这一期的推文是我发自内心觉得为数不多,特别宝贵的一篇推文,原因很简单——可参考的文献相对较少&方向非常具有研究意义&现在不卷。 数字病理方向的老师/同学应该清楚,不同中心提供的切片,染色方案是存在差异的,并且还存在各种质量问题,所以我们在数据预处理的时候,通常会先对切片的质量执行一遍筛选,然后再进行染

BZOJ 1006 神奇的国度 弦图最小染色 MCS算法

给定一个弦图,求最小染色 参考cdq的弦图与区间图论文 http://wenku.baidu.com/view/07f4be196c175f0e7cd13784.html http://tieba.baidu.com/p/2891159900 http://www.cnblogs.com/zhj5chengfeng/p/3279649.html

NOIP2010 关押罪犯 (二分答案+二分图染色)

题意:有两个监狱,N个犯人,M对关系,每对关系描述一对犯人如果在一个监狱将会产生一个冲突值。任意安排犯人的分配,使得产生的最大冲突值最小。 题解:最大值最小,先考虑二分。二分中最重要的环节就是判定猜测值可行性以及保证答案单调性。可行性判定:对于一个猜测的最大冲突值,判定时就要保证所有大于这个冲突值的两个人不能在一个监狱。只需要将需要满足不在同一监狱的两个人连上边,如果最后可以染成二分图,就存在分

二分图染色,CF1949I. Disks

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1949I - Codeforces 二、解题报告 1、思路分析 一种错误的判

算法学习笔记(二分图染色)

首先我们需要明确什么是二分图:如果无向图 G = ( V , E ) G = (V, E) G=(V,E)的所有点可以分为两个集合 V 1 、 V 2 V_1、V_2 V1​、V2​,所有的边都在 V 1 V_1 V1​和 V 2 V_2 V2​之间,而 V 1 V_1 V1​或 V 2 V_2 V2​的内部没有边,称 G G G是一个二分图。 直接说结论:如果一个图是二分图,那么它一定没有边数

bzoj2698 染色

题目链接:bzoj2698 题目大意: 有N个格子排成一排,初始时所有格子都是黑色的。现在进行M次染色操作,每次随机选取一段长度在[S,T]之间的连续段染成白色。随机选取就是所有合法的染色方案都是等概率的。求最后被染成白色的格子个数的期望值。 题解: 期望、概率 求最后被染成白色的格子个数的期望值,其实就是每个格子被染成白色的期望的和。 因为一个格子只要有一次被染成白色了就是白的了,所