洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分
正解:线段树+树链剖分
解题报告:
其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$
考虑先跑个树剖,然后按$dfn$序建线段树,区间修改区间查询就行
然后唯一要注意细节的点就因为它是查询颜色段,所以当左侧的最靠右的颜色和右侧的最靠左的颜色相同的时候要答案减一.然后在树上跳的时候也是注意这个点.
然后因为我很呆,实现在树上跳的时候就用的两个结构体分别存了两侧的数量和边界颜色.
然后我发现到最后一步两个合并的时候我分不出左右就$GG$了,,,$QAQ$
然后我又很作,如果改成直接查询数量和左右节点就简单很多了,,,但我就是不想重构然后就疯狂拍疯狂$WA$疯狂调.
调了一年总算调完了$kk$
其实理顺思路的话还是没那么难的$kk$
$over$,反正就多理下思路注意到底怎么合并就完事$kk$.
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define gc getchar()
#define t(i) edge[i].to
#define ri register int
#define rc register char
#define rb register bool
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
#define e(i,x) for(ri i=head[x];i;i=edge[i].nxt) const int N=1e5+;
int n,m,col[N],ed_cnt,head[N],dfn[N],dfn_cnt,rk[N],top[N],sz[N],sn[N],dep[N],fa[N],qwq;
struct ed{int to,nxt;}edge[N<<];
struct node{int num,l,r,tag;node(ri x=,ri y=,ri z=,ri p=){num=x,l=y,r=z,tag=p;}void print(){printf("(%d,%d,%d)",num,l,r);}}tr[N<<]; il int read()
{
rc ch=gc;ri x=;rb y=;
while(ch!='-' && (ch>'' || ch<''))ch=gc;
if(ch=='-')ch=gc,y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=gc;
return y?x:-x;
}
il bool rd(){rc ch=gc;while(ch!='C' && ch!='Q')ch=gc;return ch=='C';}
void ad(ri x,ri y){edge[++ed_cnt]=(ed){x,head[y]};head[y]=ed_cnt;}
void dfs(ri x)
{sz[x]=;e(i,x)if(!dep[t(i)]){dep[t(i)]=dep[x]+;dfs(t(i));sz[x]+=sz[t(i)];if(sz[t(i)]>sz[sn[x]])sn[x]=t(i);}}
void dfs2(ri x,ri tp)
{
top[x]=tp;rk[dfn[x]=++dfn_cnt]=x;if(sn[x])dfs2(sn[x],tp),fa[sn[x]]=x;
e(i,x)if(!top[t(i)])dfs2(t(i),t(i)),fa[t(i)]=x;
}
il node merge(node gd,node gs)
{
gd.tag=gs.tag=;if(!gd.num)return gs;if(!gs.num)return gd;
gd.num+=gs.num;if(gd.r==gs.l)--gd.num;gd.r=gs.r;return gd;
}
il void pushdown(ri nw,ri l,ri r)
{
if(!tr[nw].tag)return;
tr[nw<<]=tr[nw<<|]=(node){,tr[nw].tag,tr[nw].tag,tr[nw].tag};tr[nw].tag=;
}
void build(ri nw,ri l,ri r)
{
if(l==r)return void(tr[nw]=(node){,col[rk[l]],col[rk[l]]});
ri mid=(l+r)>>;build(nw<<,l,mid);build(nw<<|,mid+,r);tr[nw]=merge(tr[nw<<],tr[nw<<|]);
}
void modify(ri nw,ri l,ri r,ri to_l,ri to_r,ri dat)
{
if(to_l<=l && r<=to_r){return void(tr[nw]=(node){,dat,dat,dat});}
ri mid=(l+r)>>;pushdown(nw,l,r);
if(to_l<=mid)modify(nw<<,l,mid,to_l,to_r,dat);
if(to_r>mid)modify(nw<<|,mid+,r,to_l,to_r,dat);
tr[nw]=merge(tr[nw<<],tr[nw<<|]);
}
node query(ri nw,ri l,ri r,ri to_l,ri to_r)
{
if(to_l<=l && r<=to_r)return tr[nw];
ri mid=(l+r)>>;node ret;pushdown(nw,l,r);
if(to_l<=mid)ret=merge(ret,query(nw<<,l,mid,to_l,to_r));
if(to_r>mid)ret=merge(ret,query(nw<<|,mid+,r,to_l,to_r));
return ret;
} int main()
{
freopen("2486.in","r",stdin);freopen("2486.out","w",stdout);
n=read();m=read();rp(i,,n)col[i]=read();rp(i,,n-){ri x=read(),y=read();ad(x,y);ad(y,x);}
dep[]=;dfs();dfs2(,);build(,,n);
while(m--)
{
rb op=rd();
if(op)
{
ri x=read(),y=read(),z=read();
while(top[x]!=top[y])
{if(dep[top[x]]<dep[top[y]])swap(x,y);modify(,,n,dfn[top[x]],dfn[x],z);x=fa[top[x]];}
if(dep[x]<dep[y])swap(x,y);modify(,,n,dfn[y],dfn[x],z);continue;
}
ri x=read(),y=read();node asx,asy;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])
{node tmp=query(,,n,dfn[top[y]],dfn[y]);asy.num+=tmp.num-(tmp.r==asy.r);asy.r=tmp.l;y=fa[top[y]];}
else
{node tmp=query(,,n,dfn[top[x]],dfn[x]);asx.num+=tmp.num-(tmp.r==asx.r);asx.r=tmp.l;x=fa[top[x]];}
}
if(dep[x]<dep[y]){node tmp=query(,,n,dfn[x],dfn[y]);asy.num+=tmp.num-(tmp.r==asy.r);asy.r=tmp.l;}
else{node tmp=query(,,n,dfn[y],dfn[x]);asx.num+=tmp.num-(tmp.r==asx.r);asx.r=tmp.l;}
printf("%d\n",asx.num+asy.num-(asx.r==asy.r)); }
return ;
}
洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分的更多相关文章
- 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树
题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...
- 洛谷 P2486 [SDOI2011]染色(树链剖分+线段树)
题目链接 题解 比较裸的树链剖分 好像树链剖分的题都很裸 线段树中维护一个区间最左和最右的颜色,和答案 合并判断一下中间一段就可以了 比较考验代码能力 Code #include<bits/st ...
- 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)
[题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...
- 洛谷 P2486 [SDOI2011]染色 树链剖分
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 思路 PushDown与Update Q AC代码 总结与拓展 题面 题目链接 P2486 ...
- 洛谷 P4292 - [WC2010]重建计划(长链剖分+线段树)
题面传送门 我!竟!然!独!立!A!C!了!这!道!题!incredible! 首先看到这类最大化某个分式的题目,可以套路地想到分数规划,考虑二分答案 \(mid\) 并检验是否存在合法的 \(S\) ...
- 洛谷P2486 [SDOI2011]染色
题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)
#include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...
- P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)
#include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...
随机推荐
- Python基础:15私有化
默认情况下,属性在Python 中都是“public”. 1:双下划线(__) Python 为类元素(属性和方法)的私有性提供初步的形式.由双下划线开始的属性在运行时被“混淆”,所以直接访问是不允许 ...
- D - Denouncing Mafia DFS
这道题其实很简单,求k个到根的链,使得链上的节点的个数尽可能多,如果节点被计算过了,就不能再被计算了,其实我们发现,只要k>=叶子节点,那么肯定是全部,所以我们考虑所有的叶子节点,DFS到根节点 ...
- @bzoj - 3836@ [Poi2014]Tourism
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个n个点,m条边的无向图,其中你在第i个点建立旅游站点的费 ...
- oracle之简null空值问题,用nvl(a,b)函数解决
oracle之简null空值问题,用nvl(a,b)函数解决 原文链接:https://blog.csdn.net/u013821825/article/details/48766749 oracle ...
- HTML静态网页--框架
框架: 1.frameset frameset最外层的去掉body,直接用frameset 在超级链接指定目标页面显示在哪个框架窗口中 第一步:给要显示内容的目标frame设置name属性 第二步:给 ...
- halcon坐标转换(机器人坐标转换用)
#图像坐标r:=[431, 355, 507, 53, 507]c:=[505, 543, 316, 127, 883]#物理坐标(例如机器人坐标)r1:=[0, 2.0, -2.0, 10, -2. ...
- 2019-9-2-本文说如何显示SVG
title author date CreateTime categories 本文说如何显示SVG lindexi 2019-09-02 12:57:38 +0800 2018-2-13 17:23 ...
- P1103 走迷宫三
题目描述 大魔王抓住了爱丽丝,将她丢进了一口枯井中,并堵住了井口. 爱丽丝在井底发现了一张地图,他发现他现在身处一个迷宫当中,从地图中可以发现,迷宫是一个N*M的矩形,爱丽丝身处迷宫的左上角,唯一的出 ...
- AWS Credentials 使用
AWS的文档系统真是烂到家了!!!!! To connect to any of the supported services with the AWS SDK for Java, you must ...
- java 标准流
标准输入流: System.in 默认表示的是键盘录入 标准输出流: System.out 默认表示的是屏幕输出 Eg: package june6D; import java.io. ...