「SDOI2017」树点涂色 解题报告
「SDOI2017」树点涂色
我sb的不行了
其实一开始有一个类似动态dp的想法
每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色
用个set维护一下虚儿子
但是啊,我发现搞这个区间改颜色的时候,虚儿子好像得用树套树维护,我当场就不行了...
每个点如果维护到根的颜色段数\(f\)
然后发现啊,这个你如果用一个lct的一个子树维护同一种颜色,在你access的时候实变虚或者虚变实对子树有一个+1或者-1
然后额外在外面开一个线段树维护子树加减,每次access的时候操作
然后这个颜色段比较特殊,链的颜色个数可以\(f_u+f_v-f_{lca(u,v)}*2+1\),这个简单讨论一下就好了
操作3就是区间最大值
Code:
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using std::max;
template <class T>
void read(T &x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
const int N=1e5+10;
int n,m;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{
to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int mx[N<<2],tag[N<<2];
int dfn[N],low[N],dep[N],yuy[N],f[20][N],dfsclock;
int LCA(int x,int y)
{
if(dep[x]<dep[y]) std::swap(x,y);
for(int i=18;~i;i--)
if(dep[f[i][x]]>=dep[y])
x=f[i][x];
if(x==y) return x;
for(int i=18;~i;i--)
if(f[i][x]!=f[i][y])
x=f[i][x],y=f[i][y];
return f[0][x];
}
void pushdown(int id)
{
if(tag[id])
{
tag[id<<1]+=tag[id];
tag[id<<1|1]+=tag[id];
mx[id<<1]+=tag[id];
mx[id<<1|1]+=tag[id];
tag[id]=0;
}
}
void build(int id,int l,int r)
{
if(l==r) {mx[id]=yuy[l];return;}
int mid=l+r>>1;
build(id<<1,l,mid),build(id<<1|1,mid+1,r);
mx[id]=max(mx[id<<1],mx[id<<1|1]);
}
void modify(int id,int L,int R,int l,int r,int d)
{
if(l==L&&r==R)
{
mx[id]+=d;
tag[id]+=d;
return;
}
pushdown(id);
int Mid=L+R>>1;
if(r<=Mid) modify(id<<1,L,Mid,l,r,d);
else if(l>Mid) modify(id<<1|1,Mid+1,R,l,r,d);
else modify(id<<1,L,Mid,l,Mid,d),modify(id<<1|1,Mid+1,R,Mid+1,r,d);
mx[id]=max(mx[id<<1],mx[id<<1|1]);
}
int query(int id,int l,int r,int p)
{
if(l==r) return mx[id];
pushdown(id);
int mid=l+r>>1;
if(p<=mid) return query(id<<1,l,mid,p);
else return query(id<<1|1,mid+1,r,p);
}
int query(int id,int L,int R,int l,int r)
{
if(L==l&&R==r) return mx[id];
pushdown(id);
int Mid=L+R>>1;
if(r<=Mid) return query(id<<1,L,Mid,l,r);
else if(l>Mid) return query(id<<1|1,Mid+1,R,l,r);
else return max(query(id<<1,L,Mid,l,Mid),query(id<<1|1,Mid+1,R,Mid+1,r));
}
int ch[N][2],par[N],Lef[N];
#define fa par[now]
#define ls ch[now][0]
#define rs ch[now][1]
bool isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
int identity(int now){return ch[fa][1]==now;}
void connect(int f,int now,int typ){ch[fa=f][typ]=now;}
void updata(int now)
{
Lef[now]=now;
if(ls) Lef[now]=Lef[ls];
}
void Rotate(int now)
{
int typ=identity(now),p=fa;
connect(p,ch[now][typ^1],typ);
if(isroot(p)) connect(par[p],now,identity(p));
else fa=par[p];
connect(now,p,typ^1);
updata(p),updata(now);
}
void splay(int now)
{
for(;isroot(now);Rotate(now))
if(isroot(fa))
Rotate(identity(fa)^identity(now)?now:fa);
}
void access(int now)
{
for(int las=0;now;las=now,now=fa)
{
splay(now);
if(rs)
modify(1,1,n,dfn[Lef[rs]],low[Lef[rs]],1);
if(las)
modify(1,1,n,dfn[Lef[las]],low[Lef[las]],-1);
rs=las;
updata(now);
}
}
void dfs(int now,int dis)
{
dfn[now]=++dfsclock;
yuy[dfsclock]=dis;
dep[now]=dep[par[now]=f[0][now]]+1;
for(int i=1;f[i-1][now];i++) f[i][now]=f[i-1][f[i-1][now]];
for(int v,i=head[now];i;i=Next[i])
if((v=to[i])!=f[0][now])
f[0][v]=now,dfs(v,dis+1);
low[now]=dfsclock;
}
int main()
{
read(n),read(m);
for(int u,v,i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);
dfs(1,1);
build(1,1,n);
for(int op,x,y,i=1;i<=m;i++)
{
read(op),read(x);
if(op==1) access(x);
else if(op==2)
{
read(y);
printf("%d\n",query(1,1,n,dfn[x])+query(1,1,n,dfn[y])-(query(1,1,n,dfn[LCA(x,y)])<<1)+1);
}
else
printf("%d\n",query(1,1,n,dfn[x],low[x]));
}
return 0;
}
2019.4.10
「SDOI2017」树点涂色 解题报告的更多相关文章
- loj2001 「SDOI2017」树点涂色
there #include <iostream> #include <cstdio> using namespace std; int n, m, dfn[100005], ...
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...
- [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]
题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...
- 「NOI2013」小 Q 的修炼 解题报告
「NOI2013」小 Q 的修炼 第一次完整的做出一个提答,花了半个晚上+一个上午+半个下午 总体来说太慢了 对于此题,我认为的难点是观察数据并猜测性质和读入操作 我隔一会就思考这个sb字符串读起来怎 ...
- 「SCOI2015」小凸想跑步 解题报告
「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...
- 「SCOI2015」小凸解密码 解题报告
「SCOI2015」小凸解密码 题意:给一个环,定义一段连续的极长\(0\)串为\(0\)区间,定义一个位置的离一个\(0\)区间的距离为这个位置离这个区间中\(0\)的距离的最小值,每次询问一个位置 ...
- 「SCOI2015」小凸玩矩阵 解题报告
「SCOI2015」小凸玩矩阵 我好沙茶啊 把点当边连接行和列,在外面二分答案跑图的匹配就行了 我最开始二分方向搞反了,样例没过. 脑袋一抽,这绝壁要费用流,连忙打了个KM 然后wa了,一想这个不是完 ...
- 「SCOI2015」小凸玩密室 解题报告
「SCOI2015」小凸玩密室 虽然有心里在想一些奇奇怪怪的事情的原因,不过还是写太久了.. 不过这个题本身也挺厉害的 注意第一个被点亮的是任意选的,我最开始压根没注意到 \(dp_{i,j}\)代表 ...
- 「SCOI2014」方伯伯运椰子 解题报告
「SCOI2014」方伯伯运椰子 可以看出是分数规划 然后我们可以看出其实只需要改变1的流量就可以了,因为每次改变要保证流量守恒,必须流成一个环,在正负性确定的情况下,变几次是无所谓的. 然后按照套路 ...
随机推荐
- git 取消对某个文件的跟踪
git rm --cached <fileName> 例如 : git add 后,不想提交在status里的.idea/vcs.xml.操作如下:
- Android探究之View的绘制流程
Android中Activity是作为应用程序的载体存在,代表着一个完整的用户界面,提供了一个窗口来绘制各种视图,当Activity启动时,我们会通过setContentView方法来设置一个内容视图 ...
- Linux shell脚本中shift的用法说明
shift命令用于对参数的移动(左移),通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理(常见于Linux中各种程序的启动脚本). 示例1:依次读取输入的参数并打印参数个数:run ...
- SQL Server 增加链接服务器
exec sp_addlinkedserver '名称' , '' , 'SQLOLEDB' , '10.102.29.xxx' exec sp_addlinkedsrvlogin '名称' , 'f ...
- Window10上安装Redis及其客户端
资源下载地址 Redis安装包:https://github.com/MicrosoftArchive/redis/releases Redis客户端: 链接:https://pan.baidu.co ...
- maven生成项目慢解决办法
maven生成项目慢,原因:在线更新archetype-catalog.xml文件,从Apache中央仓库. 解决办法,手动下载,放到maven环境. 备用下载地址: https://files.cn ...
- Web前端教程3-JavaScript教程
目录 1. JavaScript介绍 1.1. JS嵌入页面的方式 2. JS基本语法 2.1. 变量类型 2.2. 获取元素方法 2.3. 操作元素属性 2.4. innerHTML的使用 3. J ...
- kerberos环境下spark消费kafka写入到Hbase
一.准备环境: 创建Kafka Topic和HBase表 1. 在kerberos环境下创建Kafka Topic 1.1 因为kafka默认使用的协议为PLAINTEXT,在kerberos环境下需 ...
- 解决consul覆盖注册
默认注册consul的服务id为服务名-端口号,相同的服务名和端口号注册会覆盖 解决方式: 1.自定义Consul注册Id import com.ecwid.consul.v1.ConsulClien ...
- 数据结构学习之栈求解n皇后问题
数据结构学习之栈求解n皇后问题 0x1 目的 深入掌握栈应用的算法和设计 0x2 内容 编写一个程序exp3-8.cpp求解n皇后问题. 0x3 问题描述 即在n×n的方格棋盘上,放置n个皇后 ...