cf1172E Nauuo and ODT(LCT)
首先可以转化问题,变为对每种颜色分别考虑不含该颜色的简单路径条数。然后把不是当前颜色的点视为白色,是当前颜色的点视为黑色,显然路径数量是每个白色连通块大小的平方和,然后题目变为:黑白两色的树,单点翻转颜色,维护白色连通块大小平方和,然后根据Auuan大佬的题解,我用了LCT。就是对每个点维护子树、儿子大小平方和,在 link/cut 的时候更新答案。初始化所有点是白色,离线处理每个颜色即可。
这题放在2h比赛上,除了lxl其他人都写不出来(况且lxl还是本题出题人呢)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+;
int n,m,c[N],f[N],fa[N],ch[N][],sum[N],sz[N];
ll ans,d[N],sz2[N];
bool vis[N];
vector<int>vec[N][],G[N];
bool nroot(int x){return x==ch[fa[x]][]||x==ch[fa[x]][];}
void pushup(int x){sum[x]=sum[ch[x][]]+sum[ch[x][]]+sz[x]+;}
void rotate(int x)
{
int y=fa[x],z=fa[y],w=x==ch[y][];
if(nroot(y))ch[z][y==ch[z][]]=x;
fa[x]=z,ch[y][w]=ch[x][w^],fa[ch[x][w^]]=y,ch[x][w^]=y,fa[y]=x;
pushup(y),pushup(x);
}
void splay(int x)
{
while(nroot(x))
{
int y=fa[x],z=fa[y];
if(nroot(y))
{
if((x==ch[y][])^(y==ch[z][]))rotate(x);
else rotate(y);
}
rotate(x);
}
}
void access(int x)
{
int y=;
while(x)
{
splay(x);
sz[x]+=sum[ch[x][]]-sum[y];
sz2[x]+=1ll*sum[ch[x][]]*sum[ch[x][]]-1ll*sum[y]*sum[y];
ch[x][]=y;
pushup(x);
x=fa[y=x];
}
}
int findrt(int x)
{
access(x),splay(x);
while(ch[x][])x=ch[x][];
splay(x);
return x;
}
void link(int x)
{
int y=f[x],z;
splay(x);
ans-=sz2[x]+1ll*sum[ch[x][]]*sum[ch[x][]];
z=findrt(y);
access(x),splay(z);
ans-=1ll*sum[ch[z][]]*sum[ch[z][]];
fa[x]=y;
splay(y);
sz[y]+=sum[x],sz2[y]+=1ll*sum[x]*sum[x];
pushup(y),access(x),splay(z);
ans+=1ll*sum[ch[z][]]*sum[ch[z][]];
}
void cut(int x)
{
int y=f[x],z;
access(x);
ans+=sz2[x];
z=findrt(y);
access(x),splay(z);
ans-=1ll*sum[ch[z][]]*sum[ch[z][]];
splay(x);
ch[x][]=fa[ch[x][]]=;
pushup(x),splay(z);
ans+=1ll*sum[ch[z][]]*sum[ch[z][]];
}
void dfs(int u)
{for(int i=;i<G[u].size();i++)if(G[u][i]!=f[u])f[G[u][i]]=u,dfs(G[u][i]);}
int main()
{
scanf("%d%d",&n,&m);
ll lst;
for(int i=;i<=n;i++)
scanf("%d",&c[i]),vec[c[i]][].push_back(i),vec[c[i]][].push_back();
for(int i=;i<=n+;i++)sum[i]=;
for(int i=,x,y;i<n;i++)scanf("%d%d",&x,&y),G[x].push_back(y),G[y].push_back(x);
for(int i=,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
vec[c[u]][].push_back(u),vec[c[u]][].push_back(i);
c[u]=v;
vec[v][].push_back(u),vec[v][].push_back(i);
}
f[]=n+;
dfs();
for(int i=;i<=n;i++)link(i);
for(int i=;i<=n;i++)
{
if(!vec[i][].size()){d[]+=1ll*n*n;continue;}
if(vec[i][][])d[]+=1ll*n*n,lst=1ll*n*n;else lst=;
for(int j=;j<vec[i][].size();j++)
{
int u=vec[i][][j];
if(vis[u]^=)cut(u);else link(u);
if(j==vec[i][].size()-||vec[i][][j+]!=vec[i][][j])
d[vec[i][][j]]+=ans-lst,lst=ans;
}
for(int j=vec[i][].size()-;~j;j--)
{
int u=vec[i][][j];
if(vis[u]^=)cut(u);else link(u);
}
}
ans=1ll*n*n*n;
for(int i=;i<=m;i++)ans-=d[i],printf("%lld\n",ans);
}
cf1172E Nauuo and ODT(LCT)的更多相关文章
- 【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\)计算多少条路径包含了这个颜色,不好算所以算多少条路径不包含这个颜色 ...
- 「ZJOI2018」历史(LCT)
「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...
- P4172 [WC2006]水管局长(LCT)
P4172 [WC2006]水管局长 LCT维护最小生成树,边权化点权.类似 P2387 [NOI2014]魔法森林(LCT) 离线存储询问,倒序处理,删边改加边. #include<iostr ...
- 从ZOJ2114(Transportation Network)到Link-cut-tree(LCT)
[热烈庆祝ZOJ回归] [首先声明:LCT≠动态树,前者是一种数据结构,而后者是一类问题,即:LCT—解决—>动态树] Link-cut-tree(下文统称LCT)是一种强大的数据结构,不仅可以 ...
- 【洛谷4172】 [WC2006]水管局长(LCT)
传送门 洛谷 BZOJ Solution 如果不需要动态的话,那就是一个裸的最小生成树上的最大边权对吧. 现在动态了的话,把这个过程反着来,就是加边对吧. 现在问题变成了怎么动态维护加边的最小生成树, ...
- LCT总结——应用篇(附题单)(LCT)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--概念篇戳这里 题单 灰常感谢XZY巨佬提供的强力资磁!(可参考XZY巨佬的博客总结) 题单对于系 ...
- SP16580 QTREE7 - Query on a tree VII(LCT)
题意翻译 一棵树,每个点初始有个点权和颜色(输入会给你) 0 u:询问所有u,v路径上的最大点权,要满足u,v路径上所有点颜色相同 1 u:反转u的颜色 2 u w:把u的点权改成w 题解 Qtree ...
- SP16549 QTREE6 - Query on a tree VI(LCT)
题意翻译 题目描述 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥 ...
随机推荐
- 08 SSM整合案例(企业权限管理系统):08.权限控制
04.AdminLTE的基本介绍 05.SSM整合案例的基本介绍 06.产品操作 07.订单操作 08.权限控制 09.用户操作 10.权限关联与控制 11.AOP日志 08.权限控制 SSM权限操作 ...
- js模式-观察者模式
// 主题,接收状态变化,触发每个观察者 class Subject { constructor() { this.state = 0 this.observers = [] } getState() ...
- QThread创建多线程程序
最近在阅读Qt 5.9 C++开发指南,为了加深对书本上内容的理解,参照书上的讲解尝试写了一些demo,用于以后工作中查阅,如果涉及侵权请告知,实例程序samp13_1 mythread.h #ifn ...
- Fragment 知识巩固
重新学习 Fragment 1.Fragment 的生命周期 想要熟练使用 Fragment,那么必须要弄懂它的生命周期. 我们可以先看一下 Fragment 生命周期和 Activity 生命周期的 ...
- 基于UWB技术的DW1000芯片简单解析
近些年来随着物联网和机器人技术的大发展,精确定位技术的热度也随之攀升.目前精确定位的技术有很多,如基于wifi.RFID.zigbee.超声波.UWB等技术都可以实现精准定位.由于技术的不同,精度也不 ...
- 201812-1 小明上学 Java
思路: 上学这个题和放学有区别,上学是小明每到一个路口的情况,是实时更新的.不是只有出发时间,那样就比较复杂了. 这个题需要注意:黄灯之后要等红灯,想一下交通规则. import java.util. ...
- 十分简明易懂的FFT(快速傅里叶变换)
https://blog.csdn.net/enjoy_pascal/article/details/81478582 FFT前言快速傅里叶变换 (fast Fourier transform),即利 ...
- 干货 | 京东云Kubernetes集群+Traefik实战
摘要 Traefik支持丰富的annotations配置,可配置众多出色的特性,例如:自动熔断.负载均衡策略.黑名单.白名单.所以Traefik对于微服务来说简直就是一神器. 利用Traefik,并结 ...
- try{}catch{}finally{}使用总结
import java.util.Scanner; class MyException extends Exception { public MyException(String Message) { ...
- Node.js—第一个动态页面
话不多说 上代码 没有加什么处理也不严谨 只为效果 const http=require('http'), path=require('path'), fs=require('fs') //创建服务 ...