[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写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
随机推荐
- 解决VMware虚拟机不能上网的问题
这是其中一种情况,因为使用360等加速的时候把VMware 的DHCP等服务关闭了,重新启动服务即可,方法是WIN+R 输入cmd,在doc输入services.ms打开服务,找到 把这些都启动即可
- js代码风格之链式结构
<div class="box"> <ul class="menu"> <li class="level1"& ...
- Spring MVC 项目搭建 -4- spring security-添加自定义登录页面
Spring MVC 项目搭建 -4- spring security-添加自定义登录页面 修改配置文件 <!--spring-sample-security.xml--> <!-- ...
- 浅析ConcurrentHashMap
一.导论 这些天一直在看关于多线程和高并发的书籍,也对jdk中的并发措施了解了些许,看到concurrentHashMap的时候感觉知识点很乱,有必要写篇博客整理记录一下. 当资源在多线程下共享时会产 ...
- Vijos 1002 过河 状态压缩DP
描述 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有一些石子,青蛙很讨厌踩在这些石子上.由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上 ...
- Java 9 揭秘(9. 打破模块封装)
Tips 做一个终身学习的人. 在此章节中,主要介绍以下内容: 什么是打破模块的封装 如何使用命令行选项将依赖项(添加需要)添加到模块 如何使用--add-exports命令行选项导出模块的未导出包, ...
- CentOS 6.9 升级MySQL 5.6.36到5.7.18
CentOS 6.9 升级MySQL 5.6.36到5.7.18 MySQL 5.6.36 安装过程:http://www.cnblogs.com/imweihao/p/7156754.html 升级 ...
- 如何在一个Eclipse同时启动两个Tomcat
比如:有两个版本的tomcat,一个5.*,一个6.*,此时由于两个工程分别部署在两个版本的tomcat下,需要同时启动两个tomcat,以下是方法: 1.特别要注意: 不要设置CATALINA_HO ...
- <经验杂谈>Mysql中字符串处理的几种处理方法concat、concat_ws、group_concat
Mysql中字符串处理的几种处理方法concat.concat_ws.group_concat以下详情: MySQL中concat函数使用方法:CONCAT(str1,str2,-) 返回结果为连接参 ...
- 常用http响应报文分析
这是我在使用Asp.Net的时候,整理的的一些关于Http响应报文的分析笔记,零零散散的记录, 现在贴出来,抛砖引玉,如果有什么不对或者不严谨的地方,请各位大神不吝赐教. 一.HTTP响应码响应码由三 ...