CF 1172E Nauuo and ODT ——LCT
题目:http://codeforces.com/contest/1172/problem/E
LCT好题。
考虑对每个颜色求出 “不是该颜色的点组成的连通块的 siz2 之和” 。每个颜色用 LCT 维护不是该颜色的点。
LCT 维护的一个连通块,其最顶端的点是该颜色,其他部分满足 “不是该颜色” ;再维护子树的 siz2 ,就能做了。
注意代码里的 p[ ] 要开 2*n 那么大!!!
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
ll Sqr(int x){return (ll)x*x;}
const int N=4e5+,M=N<<;
int n,m,col[N],hd[N],xnt,to[M],nxt[M];
int f[N],fa[N],c[N][],siz[N],sizi[N];
int p[M],tot; bool vis[N];ll siz2i[N],tmp,dlt[N];//p[M]!!
bool isrt(int x){return c[fa[x]][]!=x&&c[fa[x]][]!=x;}
void pshp(int x){siz[x]=siz[c[x][]]+siz[c[x][]]+sizi[x]+;}
void rotate(int x)
{
int y=fa[x],z=fa[y]; bool d=(x==c[y][]);
if(!isrt(y))c[z][y==c[z][]]=x;
fa[x]=z; fa[y]=x; fa[c[x][!d]]=y;
c[y][d]=c[x][!d]; c[x][!d]=y;
pshp(y); pshp(x);
}
void splay(int x)
{
for(int y,z;!isrt(x);rotate(x))
{
y=fa[x]; z=fa[y];
if(!isrt(y))
((y==c[z][])^(x==c[y][]))?rotate(x):rotate(y);
}
}
void access(int x)
{
for(int t=;x;t=x,x=fa[x])
{
splay(x); int y=c[x][];
sizi[x]+=siz[y]; siz2i[x]+=Sqr(siz[y]);
sizi[x]-=siz[t]; siz2i[x]-=Sqr(siz[t]);
c[x][]=t; pshp(x);
}
}
int fnd_rt(int x)
{
access(x); splay(x);
while(c[x][])x=c[x][];
splay(x); return x;
}
void link(int x)
{
splay(x);//x is top so always accessed
tmp-=Sqr(siz[c[x][]])+siz2i[x];
int y=f[x],rt=fnd_rt(y);//rt splayed
splay(rt);///y accessed
tmp-=Sqr(siz[c[rt][]]);////+siz2i[rt];
splay(y); fa[x]=y;
sizi[y]+=siz[x]; siz2i[y]+=Sqr(siz[x]); pshp(y);
access(x); splay(rt);//access(x)!!!
tmp+=Sqr(siz[c[rt][]]);
}
void cut(int x)
{
int rt=fnd_rt(x);//x accessed//rt splayed
tmp+=siz2i[x];//!!!
tmp-=Sqr(siz[c[rt][]]);
int y=f[x]; splay(y); c[y][]=; fa[x]=; pshp(y);
//x accessed and is bottom so is c[y][1]
splay(rt);
tmp+=Sqr(siz[c[rt][]]);
}
namespace Q{
int hd[N],xnt,to[M],id[M],nxt[M];
void add(int x,int y,int i)
{
to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;id[xnt]=i;
}
void solve(int cr)
{
tot=;
for(int i=hd[cr];i;i=nxt[i])
p[++tot]=i;
for(int i=tot,d;i;i--)
{
tmp=; d=p[i];
if(vis[to[d]]) link(to[d]);
else cut(to[d]);
dlt[id[d]]+=tmp;
vis[to[d]]^=;
}
}
void solve2(int cr)
{
for(int i=hd[cr];i;i=nxt[i])
{
tmp=;
if(vis[to[i]]) link(to[i]);
else cut(to[i]);
vis[to[i]]^=;
}
}
}
namespace I{
int hd[N],xnt,to[N],nxt[N];
void add(int x,int y)
{to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void solve(int cr)
{
tot=;
for(int i=hd[cr];i;i=nxt[i])
p[++tot]=to[i];
tmp=;
for(int i=tot;i;i--)
{
if(vis[p[i]]) link(p[i]);
else cut(p[i]);
vis[p[i]]^=;
}
dlt[]+=tmp;
}
void solve2(int cr)
{
for(int i=hd[cr];i;i=nxt[i])
{
tmp=;
if(vis[to[i]]) link(to[i]);
else cut(to[i]);
vis[to[i]]^=;///
}
}
}
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void ini_dfs(int cr,int fa)
{
f[cr]=fa;
for(int i=hd[cr],v;i;i=nxt[i])
if((v=to[i])!=fa) ini_dfs(v,cr);
}
int main()
{
n=rdn();m=rdn();
for(int i=;i<=n+;i++)
{ col[i]=rdn(); I::add(col[i],i);}
for(int i=,u,v;i<n;i++)
u=rdn()+,v=rdn()+,add(u,v),add(v,u);
add(,); add(,); ini_dfs(,);
for(int i=,u,d;i<=m;i++)
{
u=rdn()+; d=rdn(); Q::add(col[u],u,i);
col[u]=d; Q::add(d,u,i);
}
for(int i=;i<=n+;i++)siz[i]=;//
for(int i=;i<=n+;i++) link(i);
dlt[]=(ll)n*n*n;
for(int i=;i<=n;i++)
{
I::solve(i); Q::solve(i);
Q::solve2(i); I::solve2(i);
}
ll ans=(ll)n*n*n;
for(int i=;i<=m;i++)
{
ans-=dlt[i]; printf("%lld\n",ans);
}
return ;
}
CF 1172E Nauuo and ODT ——LCT的更多相关文章
- Codeforces 1172E Nauuo and ODT [LCT]
Codeforces ZROI那题是这题删掉修改的弱化版--ZROI还我培训费/px 思路 按照套路,我们考虑每种颜色的贡献,然后发现不包含某种颜色的路径条数更容易数,就是删掉该颜色的点后每个连通块大 ...
- 【杂题】[CodeForces 1172E] Nauuo and ODT【LCT】【口胡】
Description 给出一棵n个节点的树,每个点有一个1~n的颜色 有m次操作,每次操作修改一个点的颜色 需要在每次操作后回答树上\(n^2\)条路径每条路径经过的颜色种类数和. \(n,m< ...
- CF1172E Nauuo and ODT LCT
自己独立想出来的,超级开心 一开始想的是对于每一个点分别算这个点对答案的贡献. 但是呢,我们发现由于每一条路径的贡献是该路径颜色种类数,而每个颜色可能出现多次,所以这样就特别不好算贡献. 那么,还是上 ...
- 【CodeForces】1172E. Nauuo and ODT
题解 看了一遍题解(以及代码)但是没写代码-- 后来做梦的时候忽然梦到了这道题--意识到我需要补一下-- 这道题就是,对于每种颜色,把没有染成这种颜色的点标成黑点,然后计算每个联通块的平方 然后每个点 ...
- 【CF1172E】Nauuo and ODT(Link-Cut Tree)
[CF1172E]Nauuo and ODT(Link-Cut Tree) 题面 CF 给你一棵树,每个节点有一个颜色. 定义一条路径的权值为路径上不同颜色的数量.求所有有向路径的权值和. 有\(m\ ...
- CF1172E Nauuo and ODT
CF1172E Nauuo and ODT 神仙题orz 要算所有路径的不同颜色之和,多次修改,每次修改后询问. 对每种颜色\(c\)计算多少条路径包含了这个颜色,不好算所以算多少条路径不包含这个颜色 ...
- cf1172E Nauuo and ODT(LCT)
首先可以转化问题,变为对每种颜色分别考虑不含该颜色的简单路径条数.然后把不是当前颜色的点视为白色,是当前颜色的点视为黑色,显然路径数量是每个白色连通块大小的平方和,然后题目变为:黑白两色的树,单点翻转 ...
- [CF1172E]Nauuo and ODT:Link-Cut Tree
分析 lxl大毒瘤. 感谢Ouuan等CNOIER提供了这么好的比赛. 这里只是把官方题解复述一遍,可以直接去看官方题解:点我. 考虑将问题转化为对于每个颜色,求出没有经过这个颜色的节点的路径有多少条 ...
- 题解 CF1172E Nauuo and ODT
题目传送门 题目大意 给出一个 \(n\) 个点的树,每个点有颜色,定义 \(\text{dis}(u,v)\) 为两个点之间不同颜色个数,有 \(m\) 次修改,每次将某个点的颜色进行更改,在每次操 ...
随机推荐
- HTTP权威指南-学习笔记
目录 HTTP权威指南-学习笔记 HTTP: Web的基础 URL与资源 HTTP报文 连接管理 HTTP结构 Web服务器 代理 缓存 集成点: 网关,隧道及中继 Web机器人 识别,认证与安全 客 ...
- python的tesseract库几个重要的命令
在调用tesseract时,最重要的三个参数是 -l, -oem 和 -psm -l 参数控制识别文本的语言.可以通过命令 tesseract --list-langs 查看已经安装的字库. 支持中 ...
- 洛谷P2786 英语1(eng1)- 英语作文——map
给一手链接 https://www.luogu.com.cn/problem/P2786 拿这道题当map模板练练手qwq #include<cstdio> #include<cst ...
- Java相关面试题总结+答案(四)
[反射] 57. 什么是反射? 反射是在运行状态中,对于任意一个类,都能够知道该类的所有属性和方法,对于任意一个对象,都能够获得该对象的任一属性和方法:这种动态获取信息以及动态调用对象的方法的功能称之 ...
- Struts2之下载
下载页面 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEnco ...
- noip2018考后反思之爆0
今年又被Han老师鞭尸了TAT noip普及组比齐同学考的都差,正在准备退役Orz 哎,算了,该放题解还是要放的:( 普及第一题我觉得没有放的必要还是放一下 Code: #include<ios ...
- [BZOJ 3991][SDOI2015]寻宝游戏(dfs序)
题面 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路 ...
- P2619 [国家集训队2]Tree I(最小生成树+二分)
P2619 [国家集训队2]Tree I 每次二分一个$x$,每条白边加上$x$,跑最小生成树 统计一下满足条件的最小值就好了. to me:注意二分不要写挂 #include<iostream ...
- js IntersectionObserver api
API const options = { root: null, threshold: [0, 0.5, 1], rootMargin: '30px 100px 20px' } var io = n ...
- vim gdb使用
vim 8.0以上 :packadd termdebug :termdebug shell gdb中运行help all查看所有命令帮助 显示汇编窗口 layout asm