发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力。

痛定思痛 还是要把这道题给补了。

但是对于这道题来说 暴力还是有价值的。

考虑20分 每次暴力dfs.

考虑对于树是随机生成的 那么期望高度为logn 我们发现每次修改只用修改到1 也就是说每次暴力修改颜色的话只需要logn的时间复杂度.

考虑如何动态维护子树内的值 考虑修改一个点的颜色 子树内之前和它颜色一样的点 显然子树内部整体答案+1 如果不一样那么没有影响 和当前一样也没有影响。

考虑这个点和它的父亲此时答案是一样的如果原来答案也是一样的 那么没有任何的修改 如果不一样 那么子树内部整体-1.

依靠这个思路我们可以 维护一棵线段树 logn的时间内进行区间修改 区间查询。

考虑100分的做法 发现我们暴力慢的地方在于每次都要向上跳。

有优化的地方是 如果当前点可能树上的一段区间颜色是一样的 我们只需要在 当前修改节点x和那段颜色一样的点y的LCA处修改 剩下的直接向上跳即可。

换个角度 其实这个染颜色其实像是LCT 的ACCESS操作 这样我们就可以很方便的维护上述的操作。

考虑这样做的向上跳的复杂度 可以发现利用LCT的性质 均摊logn.

所以每次在access的时候 完成子树内部的修改即可。维护dfs序线段树 复杂度nlog^2.

const int MAXN=150010;
int n,Q,len,cnt;
int lin[MAXN],c[MAXN][2],f[MAXN],ver[MAXN<<1],nex[MAXN<<1],dfn[MAXN],out[MAXN];
int fa[MAXN],d[MAXN],sz[MAXN],son[MAXN],top[MAXN],v[MAXN];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(int x)
{
sz[x]=1;
go(x)if(tn^fa[x])
{
fa[tn]=x;d[tn]=d[x]+1;
dfs(tn);
sz[x]+=sz[tn];
if(sz[tn]>sz[son[x]])son[x]=tn;
}
}
inline void dfs(int x,int father)
{
top[x]=father;dfn[x]=++cnt;v[cnt]=x;
if(son[x])dfs(son[x],father);
go(x)if(tn!=fa[x]&&tn!=son[x])dfs(tn,tn);
out[x]=cnt;
}
inline int LCA(int x,int y)
{
while(top[x]^top[y])
{
if(d[top[x]]<d[top[y]])swap(x,y);
x=fa[top[x]];
}
return d[x]<d[y]?x:y;
}
struct seg{int tag,mx,l,r;ll sum;}t[MAXN<<2];
inline void spread(int p,int v)
{
tag(p)+=v;mx(p)+=v;
sum(p)+=(r(p)-l(p)+1)*v;
}
inline void pushdown(int p)
{
spread(zz,tag(p));
spread(yy,tag(p));
tag(p)=0;
}
inline void pushup(int p)
{
mx(p)=max(mx(zz),mx(yy));
sum(p)=sum(zz)+sum(yy);
}
inline void build(int p,int l,int r)
{
l(p)=l;r(p)=r;
if(l==r){mx(p)=d[v[l]];sum(p)=d[v[l]];return;}
int mid=(l+r)>>1;
build(zz,l,mid);build(yy,mid+1,r);
pushup(p);
}
inline void change(int p,int l,int r,int x)
{
if(l<=l(p)&&r>=r(p)){spread(p,x);return;}
int mid=(l(p)+r(p))>>1;
if(tag(p))pushdown(p);
if(l<=mid)change(zz,l,r,x);
if(r>mid)change(yy,l,r,x);
pushup(p);
}
inline int ask(int p,int x)
{
if(l(p)==r(p))return mx(p);
int mid=(l(p)+r(p))>>1;
if(tag(p))pushdown(p);
if(x<=mid)return ask(zz,x);
return ask(yy,x);
}
inline int ask(int p,int l,int r)
{
if(l<=l(p)&&r>=r(p))return mx(p);
int mid=(l(p)+r(p))>>1,w=0;
if(tag(p))pushdown(p);
if(l<=mid)w=ask(zz,l,r);
if(r>mid)w=max(w,ask(yy,l,r));
return w;
}
inline ll asksum(int p,int l,int r)
{
if(l<=l(p)&&r>=r(p))return sum(p);
int mid=(l(p)+r(p))>>1;ll w=0;
if(tag(p))pushdown(p);
if(l<=mid)w=asksum(zz,l,r);
if(r>mid)w=w+asksum(yy,l,r);
return w;
}
inline void asksum(int x)
{
ll w=asksum(1,dfn[x],out[x]);
double ans=1.0*w/sz[x];
printf("%.10lf\n",ans);
}
inline int pd(int x){return c[f[x]][1]==x||c[f[x]][0]==x;}//判断x是否为根.
inline void rotate(int x)
{
int old=f[x],oldf=f[old],k=c[old][1]==x;
c[old][k]=c[x][k^1];c[x][k^1]=old;
if(pd(old))c[oldf][c[oldf][1]==old]=x;
if(c[old][k])f[c[old][k]]=old;
f[old]=x;f[x]=oldf;
}
inline void splay(int x)
{
while(pd(x))
{
if(pd(f[x]))rotate((c[f[x]][1]==x)^(c[f[f[x]]][1]==f[x])?x:f[x]);
rotate(x);
}
}
inline int findroot(int x)
{
splay(x);
while(c[x][0])x=c[x][0];
splay(x);return x;
}
inline void access(int x)
{
int y=0;
while(x)
{
splay(x);
if(c[x][1])
{
int w=c[x][1];
c[x][1]=0;
w=findroot(w);
change(1,dfn[w],out[w],1);
}
if(y)
{
y=findroot(y);
change(1,dfn[y],out[y],-1);
}
c[x][1]=y;
y=x;x=f[x];
}
}
int main()
{
freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
get(n);
rep(2,n,i)
{
int x,y;
get(x)+1;get(y)+1;
//cout<<x<<' '<<y<<endl;
add(x,y);add(y,x);
}
get(Q);dfs(1);dfs(1,1);
build(1,1,n);
rep(1,n,i)f[i]=fa[i];
rep(1,Q,i)
{
char ch=getc();
while(ch!='q'&&ch!='O')ch=getc();
int get(x)+1;
if(ch=='O')access(x);
else asksum(x);
}
return 0;
}

3.28 省选模拟赛 染色 LCT+线段树的更多相关文章

  1. 4.11 省选模拟赛 序列 二分 线段树优化dp set优化dp 缩点

    容易想到二分. 看到第一个条件容易想到缩点. 第二个条件自然是分段 然后让总和最小 容易想到dp. 缩点为先:我是采用了取了一个前缀最小值数组 二分+并查集缩点 当然也是可以直接采用 其他的奇奇怪怪的 ...

  2. 6.18 省选模拟赛 字符串 LCT SAM

    LINK:字符串 看起来很难做 考虑一种暴力 建立SAM后每次查询暴力扫儿子. 期望得分10分.实际得分10分. 另外一种发现每次扫儿子过于暴力 可以每次儿子向上做贡献 每次都暴力向上跳. 期望得分1 ...

  3. 6.3 省选模拟赛 Decompose 动态dp 树链剖分 set

    LINK:Decompose 看起来很难 实际上也很难 考验选手的dp 树链剖分 矩阵乘法的能力. 容易列出dp方程 暴力dp 期望得分28. 对于链的情况 容易发现dp方程可以转矩阵乘法 然后利用线 ...

  4. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  5. 【Foreign】染色 [LCT][线段树]

    染色 Time Limit: 20 Sec  Memory Limit: 256 MB Description Input Output Sample Input 13 0 1 0 2 1 11 1 ...

  6. 4.17 省选模拟赛 远行 LCT 启发式合并 倍增

    容易写出nQ的暴力 由于数据是期望的时间 所以直接dfs可以跑的很快 可以拿到70分. 当然 可以进一步优化暴力 使用换根dp 然后可以将暴力优化到n^2. const int MAXN=300010 ...

  7. 4.28 省选模拟赛 负环 倍增 矩阵乘法 dp

    容易想到 这个环一定是简单环. 考虑如果是复杂环 那么显然对于其中的第一个简单环来说 要么其权值为负 如果为正没必要走一圈 走一部分即可. 对于前者 显然可以找到更小的 对于第二部分是递归定义的. 综 ...

  8. 4.28 省选模拟赛模拟赛 最佳农场 二维卷积 NTT

    第一次遇到二维卷积 不太清楚是怎么做的. 40分暴力比对即可. 对于行为或者列为1时 容易想到NTT做快速匹配.然后找答案即可. 考虑这是一个二维的比对过程. 设\(f_{i,j}\)表示以i,j为右 ...

  9. 4.12 省选模拟赛 LCA on tree 树链剖分 树状数组 分析答案变化量

    LINK:duoxiao OJ LCA on Tree 题目: 一道树链剖分+树状数组的神题. (直接nQ的暴力有50. 其实对于树随机的时候不难想到一个算法 对于x的修改 暴力修改到根. 对于儿子的 ...

随机推荐

  1. css样式大全,完整的Css样式大全(整理)

    CSS样式被称为为“层叠样式表”,是一种网页制作做不可或缺的技术,是用于装饰网页,达到设计效果的一种样式语言,下面将整理一下css常用样式: 字体属性:(font) 大小 {font-size: x- ...

  2. MySQL 你可能忽视的选择问题

    我们在 MySQL 入门篇主要介绍了基本的 SQL 命令.数据类型和函数,在局部以上知识后,你就可以进行 MySQL 的开发工作了,但是如果要成为一个合格的开发人员,你还要具备一些更高级的技能,下面我 ...

  3. HDU 2157 How many ways?? 题解

    题目 春天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这迷人的校园, 葱头决定, 每次上课都走不同的路线 ...

  4. 为什么有时候人们用translate来改变位置而不是定位?

    translate()是transform的一个值. 改变transform或opacity不会触发浏览器重新布局(reflow)或重绘(repaint),只会触发复合(compositions)(复 ...

  5. SpringBoot入门详细教程

    一.SpringBoot入门 1.SpringBoot简介 SpringBoot是整个Spring技术栈的整合,来简化Spring应用开发,约定大于配置,去繁从简,just run 就能创建一 个独立 ...

  6. Web For Pentester靶场(xss部分)

    配置 官网:https://pentesterlab.com/ 下载地址:https://isos.pentesterlab.com/web_for_pentester_i386.iso 安装方法:虚 ...

  7. Spring常见问题大全

    Spring 概述 1. 什么是spring? Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring ...

  8. Web Scraping using Python Scrapy_BS4 - using BeautifulSoup and Python

    Use BeautifulSoup and Python to scrap a website Lib: urllib Parsing HTML Data Web scraping script fr ...

  9. 使用PowerShell自动编译部署前端

    前言 最近在开发一套管理系统,做了前后端分离. 后台使用的是Asp.Net Core 3.1 前端使用的是Vue+Ant Design 自己搞了一台云服务器,打算把系统部署到云服务器上.以供外网访问. ...

  10. Mock分页

    前后端分离开发时,一般会使用mock. 因为mock是用node运行的,行为与调用后台一致. 这样,不需要等后台写好,只要有接口文档,前端可以自己调接口,这样联调时遇到的问题会少很多,可以加快整体开发 ...