首先可以转化问题,变为对每种颜色分别考虑不含该颜色的简单路径条数。然后把不是当前颜色的点视为白色,是当前颜色的点视为黑色,显然路径数量是每个白色连通块大小的平方和,然后题目变为:黑白两色的树,单点翻转颜色,维护白色连通块大小平方和,然后根据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)的更多相关文章

  1. 【CF1172E】Nauuo and ODT(Link-Cut Tree)

    [CF1172E]Nauuo and ODT(Link-Cut Tree) 题面 CF 给你一棵树,每个节点有一个颜色. 定义一条路径的权值为路径上不同颜色的数量.求所有有向路径的权值和. 有\(m\ ...

  2. CF1172E Nauuo and ODT

    CF1172E Nauuo and ODT 神仙题orz 要算所有路径的不同颜色之和,多次修改,每次修改后询问. 对每种颜色\(c\)计算多少条路径包含了这个颜色,不好算所以算多少条路径不包含这个颜色 ...

  3. 「ZJOI2018」历史(LCT)

    「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...

  4. P4172 [WC2006]水管局长(LCT)

    P4172 [WC2006]水管局长 LCT维护最小生成树,边权化点权.类似 P2387 [NOI2014]魔法森林(LCT) 离线存储询问,倒序处理,删边改加边. #include<iostr ...

  5. 从ZOJ2114(Transportation Network)到Link-cut-tree(LCT)

    [热烈庆祝ZOJ回归] [首先声明:LCT≠动态树,前者是一种数据结构,而后者是一类问题,即:LCT—解决—>动态树] Link-cut-tree(下文统称LCT)是一种强大的数据结构,不仅可以 ...

  6. 【洛谷4172】 [WC2006]水管局长(LCT)

    传送门 洛谷 BZOJ Solution 如果不需要动态的话,那就是一个裸的最小生成树上的最大边权对吧. 现在动态了的话,把这个过程反着来,就是加边对吧. 现在问题变成了怎么动态维护加边的最小生成树, ...

  7. LCT总结——应用篇(附题单)(LCT)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--概念篇戳这里 题单 灰常感谢XZY巨佬提供的强力资磁!(可参考XZY巨佬的博客总结) 题单对于系 ...

  8. SP16580 QTREE7 - Query on a tree VII(LCT)

    题意翻译 一棵树,每个点初始有个点权和颜色(输入会给你) 0 u:询问所有u,v路径上的最大点权,要满足u,v路径上所有点颜色相同 1 u:反转u的颜色 2 u w:把u的点权改成w 题解 Qtree ...

  9. SP16549 QTREE6 - Query on a tree VI(LCT)

    题意翻译 题目描述 给你一棵n个点的树,编号1~n.每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我们看: 0 u:询问有多少个节点v满足路径u到v上所有节点(包括)都拥 ...

随机推荐

  1. 2016蓝桥杯省赛C/C++A组第八题 四平方和

    题意: 四平方和定理,又称为拉格朗日定理: 每个正整数都可以表示为至多4个正整数的平方和. 如果把0包括进去,就正好可以表示为4个数的平方和. 比如: 5 = 0^2 + 0^2 + 1^2 + 2^ ...

  2. vs使用opencv总提示igdrclneo64.dll异常.exe: 0xC0000005:的解决方法

    最近项目中要使用opencv库,搭建好环境,使用接口的时候,总提示 igdrclneo64.dll报错崩溃,一直怀疑是自己程序的问题,后面经过一系列的查资料才解决 解决办法: 本地环境:vs2015+ ...

  3. C++基础--智能指针

    智能指针其实也不是完全的指针,应该说是像指针一样的类对象,智能指针通常有指针的功能,当然同时也包含了一些额外的功能.目前比较常见的智能指针有auto_ptr.unique_ptr和shared_ptr ...

  4. C#后台执行JavaScript

    方法一: Page.RegisterClientScriptBlock 方法 命名空間: System.Web.UI 这个方法现在已经过时.改用ClientScriptManager.Register ...

  5. POJ-3258 (最小值最大化问题)

    POJ - 3258 River Hopscotch Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & ...

  6. PrepareStatement对象进行批处理的典型步骤顺序

    https://www.yiibai.com/jdbc/preparestatement-batching-example.html 以下是使用PrepareStatement对象进行批处理的典型步骤 ...

  7. DevOps专题|基础Agent部署系统

    随着京东云业务规模.管理机器规模的扩大,各类agent也在逐渐增多,如日志agent.监控agent.控制系统agent等.这对agent的部署.升级.状态维护提出了很高的要求,一旦某个全局agent ...

  8. MySQL的异常问题

    异常问题

  9. INSTALL_FAILED_SHARED_USER_INCOMPATIBLE错误解决

    Target device: smartisan-yq601-3fa1a5dcInstalling APK: /Users/wangliang/workspace/emm-android/build/ ...

  10. 实盘交易哪些代码BUG产生严重亏损

    1.少写一个return,疯狂开平2900次,以爆仓结束 2.在上生产环境前,不小心误删除了一个“!”(我至今也不清楚为什么会误删了,晕),导致平仓逻辑一直不满足,不止损,让我损失惨重! 3.卖单变买 ...