「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

最新文章

  1. Linux C语言解析.bmp格式图片并显示汉字
  2. weui 多网页切换效果分析
  3. Python爬虫学习(1): urllib的使用
  4. Spring源码学习之:FactoryBean的使用
  5. SHA-1 加密算法破解现已只需要 10 天
  6. etcd相关资料
  7. C#中DataTable排序、检索、合并等操作实例
  8. 学习swift开源项目
  9. X230上安装Yosemite/Win7-黑苹果之路
  10. Codeforces Round #333 DIV2
  11. C#- 布署WinForm程序
  12. 使用solr搭建你的全文检索
  13. avconv转换视频
  14. Linux硬盘命名和安装分区
  15. ios7 实现应用内保真截屏
  16. 关机和重启Linux命令
  17. C/C++ 知识点---sizeof使用规则及陷阱分析(网摘)
  18. [js高手之路] 设计模式系列课程 - jQuery的链式调用与灵活的构造函数
  19. 一份从0到1的java项目实践清单
  20. PDO::__construct(): Server sent charset (255) unknown to the client. Please, report to the developers

热门文章

  1. iis正确安装了,但是还是无法访问,这是iis和.net安装顺序问题,记录一下
  2. JavaScript基础-3
  3. CSS3 弹性盒子
  4. Nginx日志常用统计分析命令
  5. java笔记----property文件读写
  6. NPM -- 初探--01
  7. djangorestframework+vue-cli+axios,为axios添加token作为headers踩坑记
  8. 使用Linq的过程中碰到的问题
  9. liteos简介(一)
  10. [转]Lua和Lua JIT及优化指南