[SDOI2011]染色 线段树+树链剖分
考试一共四个半小时,光这道题就打了三个小时。。然后又改了俩小时才过。我太蒟蒻了。
其实数据结构这种题就看第一遍打没打顺,顺了就A了,要是再找错再改就慢了,而且样例过了不能说明任何问题(虽然考试的时候我连样例都没出hhh)
void pushup(int root) { tree[root].lcol=tree[root<<1].lcol; tree[root].rcol=tree[root<<1|1].rcol; if(tree[root<<1].rcol==tree[root<<1|1].lcol) tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan-1; else tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan; }
这段pushup想必大家就明白怎么递归了。
注意在往上爬的过程当中,一段一段中间的连接区域可能会有颜色相同,需要判断一下,找出fx。
完整代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; #define N 500000 #define pos(i,a,b) for(int i=(a);i<=(b);i++) int n,m; int v[N]; struct haha { int next,to; }edge[N]; int head[N],cnt=1; struct qian { int left,right; int lcol,rcol,duan; }tree[N]; int duan[N]; void add(int u,int v) { edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } int rt[N]; int size[N],son[N],dep[N],fa[N]; void dfs1(int x) { size[x]=1;son[x]=0; for(int i=head[x];i;i=edge[i].next) { int to=edge[i].to; if(to!=fa[x]) { fa[to]=x; dep[to]=dep[x]+1; dfs1(to); size[x]+=size[to]; if(size[to]>size[son[x]]) son[x]=to; } } } int id[N],pos[N],top[N]; int ji; void dfs2(int x,int tp) { top[x]=tp; id[x]=++ji; pos[ji]=x; if(son[x]) dfs2(son[x],tp); for(int i=head[x];i;i=edge[i].next) { int to=edge[i].to; if(to!=fa[x]&&to!=son[x]) dfs2(to,to); } } void pushup(int root) { tree[root].lcol=tree[root<<1].lcol; tree[root].rcol=tree[root<<1|1].rcol; if(tree[root<<1].rcol==tree[root<<1|1].lcol) tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan-1; else tree[root].duan=tree[root<<1].duan+tree[root<<1|1].duan; } void build(int left,int right,int root) { rt[root]=-1; tree[root].left=left; tree[root].right=right; if(left==right) { tree[root].lcol=tree[root].rcol=v[pos[left]]; tree[root].duan=1; return; } int mid=(left+right)>>1; build(left,mid,root<<1); build(mid+1,right,root<<1|1); pushup(root); } void pushdown(int root) { if(rt[root]>=0) { rt[root<<1]=rt[root]; rt[root<<1|1]=rt[root]; tree[root<<1].lcol=tree[root<<1].rcol=rt[root]; tree[root<<1|1].lcol=tree[root<<1|1].rcol=rt[root]; tree[root<<1].duan=tree[root<<1|1].duan=1; rt[root]=-1; } } void change(int left,int right,int num,int root) { if(left<=tree[root].left&&right>=tree[root].right) { rt[root]=num; tree[root].lcol=tree[root].rcol=num; tree[root].duan=1; return; } pushdown(root); int mid=(tree[root].right+tree[root].left)>>1; if(left<=mid) change(left,right,num,root<<1); if(right>mid) change(left,right,num,root<<1|1); pushup(root); } int query(int left,int right,int root) { if(left<=tree[root].left&&right>=tree[root].right) return tree[root].duan; pushdown(root); int mid=(tree[root].left+tree[root].right)>>1; if(right<=mid) return query(left,right,root<<1); else if(left>mid) return query(left,right,root<<1|1); else { int tmp=1; if(tree[root<<1].rcol!=tree[root<<1|1].lcol) tmp=0; return query(left,mid,root<<1)+query(mid+1,right,root<<1|1)-tmp; } } int temp1,temp2; void check(int po,int root) { pushdown(root); if(tree[root].left==tree[root].right) { temp1=tree[root].lcol; return; } int mid=(tree[root].right+tree[root].left)>>1; if(po<=mid) check(po,root<<1); else check(po,root<<1|1); } void check2(int po,int root) { pushdown(root); if(tree[root].left==tree[root].right) { temp2=tree[root].lcol; return; } int mid=(tree[root].right+tree[root].left)>>1; if(po<=mid) check2(po,root<<1); else check2(po,root<<1|1); } int erx,fux,ery,fuy; int Query(int x,int y) { int fx=top[x],fy=top[y]; int ans=0; while(fx!=fy) { if(dep[fx]>dep[fy]) { check(id[fa[fx]],1); check2(id[fx],1); ans+=query(id[fx],id[x],1); if(temp1==temp2) ans--; x=fa[fx]; fux=x; erx=fx; fx=top[x]; } else { check(id[fa[fy]],1); check2(id[fy],1); ans+=query(id[fy],id[y],1); if(temp1==temp2) ans--; y=fa[fy]; fuy=y; ery=fy; fy=top[y]; } } if(dep[x]>dep[y]) { //check(id[erx],1); //check(id[fux],1); ans+=query(id[y],id[x],1); //if(temp1==temp2) //ans--; } else { //check(id[ery],1); //check(id[fuy],1); ans+=query(id[x],id[y],1); //if(temp1==temp2) //ans--; } return ans; } void Change(int x,int y,int z) { int fx=top[x],fy=top[y]; while(fx!=fy) { if(dep[fx]<dep[fy]) { swap(fx,fy); swap(x,y); } change(id[fx],id[x],z,1); x=fa[fx];fx=top[x]; } if(dep[x]>dep[y]) swap(x,y); change(id[x],id[y],z,1); } int read() { int su=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch<='9'&&ch>='0') { su=su*10+ch-'0'; ch=getchar(); } return su; } int main() { //freopen("paint6.in","r",stdin); //freopen("paint66.out","w",stdout); scanf("%d%d",&n,&m); pos(i,1,n) v[i]=read(); pos(i,1,n-1) { int x,y; x=read();y=read(); add(x,y); add(y,x); } dfs1(1); dfs2(1,1); build(1,n,1); pos(i,1,m) { char p; int x,y,z; scanf("%s",&p); if(p=='C') { x=read();y=read();z=read(); Change(x,y,z); } if(p=='Q') { x=read();y=read(); printf("%d\n",Query(x,y)); } } //while(1); return 0; }
[SDOI2011]染色 线段树+树链剖分的更多相关文章
- bzoj 2243: [SDOI2011]染色 线段树区间合并+树链剖分
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 7925 Solved: 2975[Submit][Status ...
- 洛谷$P2486\ [SDOI2011]$染色 线段树+树链剖分
正解:线段树+树链剖分 解题报告: 传送门$QwQ$ 其实是道蛮板子的题,,,但因为我写得很呆然后写了贼久之后发现想法有问题要重构,就很难受,就先写个题解算了$kk$ 考虑先跑个树剖,然后按$dfn$ ...
- [BZOJ2243][SDOI2011]染色 解题报告|树链剖分
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- [Bzoj2243][SDOI2011]染色(线段树&&树剖||LCT)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2243 线段树+树链剖分,在线段树需要每次用lt和rt两个数组记录当前区间的左右边界的颜色 ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- bzoj2243: [SDOI2011]染色--线段树+树链剖分
此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...
- 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), ...
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
随机推荐
- Mathematica 10 Mac 设置默认工作目录
用SetDirectory命令设置
- Object-C知识点 (四) 性能优化
#pragma mark - 性能优化 1. 行高一定要缓存 缓存行高是解决性能优化的最佳途径(除非刷新频率已经很高了,否则一定要缓存)2. 尽量减少计算,所有需要素材提前计算好3. 控件不要设置圆角 ...
- linux命令行解刨
linux命令需要在命令行界面上操作(windows的cmd也是一个命令行界面).只有在了解命令行界面含义才能知道我们输入这些命令意义是什么,为什么要输入这些命令. 首先我们要知道怎么找出linux输 ...
- set-集合功能介绍
叨逼叨:#集合 不可重复的列表 可变类型#1.添加 无则添加有则不操作 不可重复 # se = {'alex','eric','seven'} # se.add('qiqi') # se.add('b ...
- Apple使用Apache Mesos重建Siri后端服务
苹果公司宣布,将使用开源的集群管理软件Apache Mesos,作为该公司广受欢迎的.基于iOS的智能个人助理软件Siri的后端服务.Mesosphere的博客指出,苹果已经创建了一个命名为J.A.R ...
- Entity Framework Core 软删除与查询过滤器
本文翻译自<Entity Framework Core: Soft Delete using Query Filters>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 注意 ...
- DDD理论学习系列(11)-- 工厂
DDD理论学习系列--案例及目录 1.引言 在针对大型的复杂领域进行建模时,聚合.实体和值对象之间的依赖关系可能会变得十分复杂.在某个对象中为了确保其依赖对象的有效实例被创建,需要深入了解对象实例化逻 ...
- css 子div自适应父div高度
<div class="out"> <div class="a"></div> <div class="b& ...
- 关于table表格td里内容是数字而且太长不换行的问题
<p>table{table-layout:fixed}</p><p>table td{word-wrap:break-word}</p><p&g ...
- 设计模式的征途—14.职责链(Chain of Responsibility)模式
相信大家都玩过类似于“斗地主”的纸牌游戏,某人出牌给他的下家,下家看看手中的牌,如果要不起,则将出牌请求转发给他的下家,其下家再进行判断.一个循环下来,如果其他人都要不起该牌,则最初的出牌者可以打出新 ...