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\) 次修改,每次将某个点的颜色进行更改,在每次操 ...
随机推荐
- 测开之路七十:监控平台之html
监控平台的html <!-- 继承base模板 -->{% extends "base.html" %} <!-- 引入bootstrap-datetimepic ...
- Vagrant 手册之 Vagrantfile - 概述
原文地址 Vagrantfile 的主要用途是描述用于项目的机器类型,以及如何配置和提供这些机器. Vagrant 的每个项目运行一个 Vagrantfile,并且 Vagrantfile 应该被提交 ...
- Buy Tickets 【POJ - 2828】【线段树】
题目链接 有N次操作,每次都是将第i个数放置在第pos个数的后面,并且这个数的值是val. 这个线段树的思维确实很好,我们可以发现,后面放进去的数,一定是强制位置的,而前面放的数,会随着后面的数进入而 ...
- HNOI2019fish
\({\rm fish}\) 20分: 六个for,点积判锐角钝角. #include <vector> #include <queue> #include <cmath ...
- css中word-break、word-wrap和white-space的区别
css中word-break.word-wrap和white-space的区别 :https://baijiahao.baidu.com/s?id=1578623236521030997&wf ...
- 点分治题单(来自XZY)
点分治题单(来自XZY) 静态点分治 [x] 洛谷 P3806 [模板]点分治1 [x] 洛谷 P4178 Tree [x] 洛谷 P2634 [国家集训队]聪聪可可 [x] 洛谷 P4149 [IO ...
- Gradle 入门--只此一篇
是什么? 在语法上是基于Groovy语言的(Groovy 是一种基于JVM的敏捷开发语言,可以简单的理解为强类型语言java的弱类型版本),在项目管理上是基于Ant和Maven概念的项目自动化建构工具 ...
- Java负整数的左移、右移、无符号右移
转自 Java负整数的左移.右移.无符号右移 Java负整数的左移.右移.无符号右移.正数的位移没有涉及到符号,而且正数的原码.反码.补码都是一样的,所以相对简单,但是对于负整数的位移,往往容易混淆 ...
- linux单机部署kafka(filebeat+elk组合)
filebeat+elk组合之kafka单机部署 准备: kafka下载链接地址:http://kafka.apache.org/downloads.html 在这里下载kafka_2.12-2.10 ...
- 一、简单的图片上传并预览功能input[file]
一.简单的图片上传并预览功能input[file] <!DOCTYPE html> <html lang="en"> <head> <me ...