CF1172E Nauuo and ODT


神仙题orz

要算所有路径的不同颜色之和,多次修改,每次修改后询问。

对每种颜色\(c\)计算多少条路径包含了这个颜色,不好算所以算多少条路径不包含这个颜色。颜色是\(c\)的标黑,否则标白,要算的就是黑连通块的\(\sum siz^2\)

对每种颜色用LCT维护连通块。拿出有关的所有操作,动态维护所有连通块的\(\sum siz^2\)。

(这里有一个trick,黑点向父亲连边,连通块就是连通块去掉根。)

要维护的东西有实子树大小、虚子树大小和虚子树平方和。

每次link、cut时先减去原来连通块贡献,然后加上新的。

口胡一下好简单啊,然后照着yyb写了一遍

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))f^=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
int c[400010],FA[400010];
ll SUM,ans[400010];
int fa[400010],ch[400010][2],siz[400010],_siz[400010],cnt;
ll _siz2[400010];
il ll sqr(int x){return 1ll*x*x;}
bool rev[400010];
std::vector<std::pair<int,int>>G[400010];
int qu[400010],qx[400010];
namespace tree{
int fir[400010],dis[800010],nxt[800010],id;
il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
il vd dfs(int x){
for(int i=fir[x];i;i=nxt[i]){
if(FA[x]==dis[i])continue;
FA[dis[i]]=x;dfs(dis[i]);
}
}
}
il bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
il vd upd(int x){if(x)siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+_siz[x]+1;}
il vd Rev(int x){if(x)rev[x]^=1,std::swap(ch[x][0],ch[x][1]);}
il vd down(int x){
if(!x)return;
if(!isrt(x))down(fa[x]);
if(rev[x])Rev(ch[x][0]),Rev(ch[x][1]),rev[x]=0;
}
il vd rotate(int x){
int y=fa[x],z=fa[y],o=x==ch[y][1];
if(!isrt(y))ch[z][y==ch[z][1]]=x;fa[x]=z;
ch[y][o]=ch[x][!o];fa[ch[x][!o]]=y;
ch[x][!o]=y;fa[y]=x;
upd(y);
}
il vd splay(int x){
if(!x)return;
down(x);int y,z;
while(!isrt(x)){
y=fa[x],z=fa[y];
if(!isrt(y))rotate(((ch[y][0]==x)^(ch[z][0]==y))?x:y);
rotate(x);
}
upd(x);
}
il vd access(int x){for(int y=0;x;x=fa[y=x])splay(x),_siz[x]+=siz[ch[x][1]]-siz[y],_siz2[x]+=sqr(siz[ch[x][1]])-sqr(siz[y]),ch[x][1]=y,upd(x);}
il int find(int x){access(x),splay(x);while(ch[x][0])x=ch[x][0];splay(x);return x;}
il vd makert(int x){splay(x);access(x);rev[x]^=1;}
il vd link(int x,int y){//y==FA[x]
splay(x);SUM-=sqr(siz[ch[x][1]])+_siz2[x];
int z=find(y);
access(x);splay(z);SUM-=sqr(siz[ch[z][1]]);
splay(y);fa[x]=y;_siz[y]+=siz[x];_siz2[y]+=sqr(siz[x]);
upd(y);
access(x);splay(z);SUM+=sqr(siz[ch[z][1]]);
}
il vd cut(int x,int y){
access(x);SUM+=_siz2[x];
int z=find(y);
access(x);splay(z);SUM-=sqr(siz[ch[z][1]]);
splay(y);splay(x);
ch[x][0]=fa[y]=0;upd(x);
splay(z);SUM+=sqr(siz[ch[z][1]]);
}
bool nowcol[400010];
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n=gi(),m=gi(),a,b;
for(int i=1;i<=n;++i)c[i]=gi();
for(int i=1;i<n;++i)a=gi(),b=gi(),tree::link(a,b),tree::link(b,a);
tree::dfs(1);
FA[1]=n+1;
for(int i=1;i<=n;++i)siz[i]=1;
for(int i=1;i<=n;++i)link(i,FA[i]);
for(int i=1;i<=n;++i)G[c[i]].push_back({i,0});
for(int i=1;i<=m;++i){
qu[i]=gi(),qx[i]=gi();
G[c[qu[i]]].push_back({qu[i],i});
G[c[qu[i]]=qx[i]].push_back({qu[i],i});
}
for(int i=1;i<=n;++i){
ll lst=0;
for(auto j:G[i]){
int x=j.first,t=j.second;
if(nowcol[x])nowcol[x]=0,link(x,FA[x]);
else nowcol[x]=1,cut(x,FA[x]);
ans[t]+=1ll*n*n-SUM-lst;
lst=1ll*n*n-SUM;
}
for(auto j:G[i])if(nowcol[j.first])nowcol[j.first]=0,link(j.first,FA[j.first]);
}
for(int i=1;i<=m;++i)ans[i]+=ans[i-1];
for(int i=0;i<=m;++i)printf("%lld\n",ans[i]);
return 0;
}

CF1172E Nauuo and ODT的更多相关文章

  1. CF1172E Nauuo and ODT LCT

    自己独立想出来的,超级开心 一开始想的是对于每一个点分别算这个点对答案的贡献. 但是呢,我们发现由于每一条路径的贡献是该路径颜色种类数,而每个颜色可能出现多次,所以这样就特别不好算贡献. 那么,还是上 ...

  2. [CF1172E]Nauuo and ODT:Link-Cut Tree

    分析 lxl大毒瘤. 感谢Ouuan等CNOIER提供了这么好的比赛. 这里只是把官方题解复述一遍,可以直接去看官方题解:点我. 考虑将问题转化为对于每个颜色,求出没有经过这个颜色的节点的路径有多少条 ...

  3. cf1172E Nauuo and ODT(LCT)

    首先可以转化问题,变为对每种颜色分别考虑不含该颜色的简单路径条数.然后把不是当前颜色的点视为白色,是当前颜色的点视为黑色,显然路径数量是每个白色连通块大小的平方和,然后题目变为:黑白两色的树,单点翻转 ...

  4. 题解 CF1172E Nauuo and ODT

    题目传送门 题目大意 给出一个 \(n\) 个点的树,每个点有颜色,定义 \(\text{dis}(u,v)\) 为两个点之间不同颜色个数,有 \(m\) 次修改,每次将某个点的颜色进行更改,在每次操 ...

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

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

  6. Codeforces 1172E Nauuo and ODT [LCT]

    Codeforces ZROI那题是这题删掉修改的弱化版--ZROI还我培训费/px 思路 按照套路,我们考虑每种颜色的贡献,然后发现不包含某种颜色的路径条数更容易数,就是删掉该颜色的点后每个连通块大 ...

  7. 【CodeForces】1172E. Nauuo and ODT

    题解 看了一遍题解(以及代码)但是没写代码-- 后来做梦的时候忽然梦到了这道题--意识到我需要补一下-- 这道题就是,对于每种颜色,把没有染成这种颜色的点标成黑点,然后计算每个联通块的平方 然后每个点 ...

  8. 【杂题】[CodeForces 1172E] Nauuo and ODT【LCT】【口胡】

    Description 给出一棵n个节点的树,每个点有一个1~n的颜色 有m次操作,每次操作修改一个点的颜色 需要在每次操作后回答树上\(n^2\)条路径每条路径经过的颜色种类数和. \(n,m< ...

  9. CF 1172E Nauuo and ODT ——LCT

    题目:http://codeforces.com/contest/1172/problem/E LCT好题. 考虑对每个颜色求出 “不是该颜色的点组成的连通块的 siz2 之和” .每个颜色用 LCT ...

随机推荐

  1. ELK学习笔记之使用curl命令操作elasticsearch

    0x00 _cat系列 _cat系列提供了一系列查询elasticsearch集群状态的接口.你可以通过执行curl -XGET localhost:9200/_cat 1. 获取所有_cat系列的操 ...

  2. Linux 6 修改ssh默认远程端口号

    linux 默认的ssh远程端口是22,有时默认端口会遭到别有用心的人们扫描或攻击,为了时我们的系统更加安全那就需要修改远程端口号 操作步骤:1.修改ssh_config配置文件 vim /etc/s ...

  3. :阿里巴巴 Java 开发手册 (十一)工程结构

    (一) 应用分层 1. [推荐]图中默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于 Web 层,也可以直接依赖于 Service 层,依此类推:  开放接口层:可直接封装 Se ...

  4. 如何在Mybatis的xml文件调用java类的方法

    在mybatis的映射xml文件调用java类的方法:使用的是OGNL表达式,表达式格式为:${@prefix@methodName(传递参数名称)} 1.如下代码所示:方法必须为静态方法:以下我只是 ...

  5. 2019 讯飞java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.讯飞等公司offer,岗位是Java后端开发,因为发展原因最终选择去了讯飞,入职一年时间了,也成为了面试官,之 ...

  6. 自学Python编程的第\七天----------来自苦逼的转行人

    2019-09-17-23:09:48 今天学的内容是有关小数据池的,学的有点懵逼,感觉越来越难学了,但是得坚持下去 明天学习下一个课程时,感觉要跟不上,看来明天得先看好几遍今天的内容 不然肯定会听的 ...

  7. Vue v-bind与v-model的区别

    v-bind    缩写 : 动态地绑定一个或多个特性,或一个组件 prop 到表达式. 官网举例   <!-- 绑定一个属性 -->   <img v-bind:src=" ...

  8. win10设置锁屏密码

    1.点击右下角窗口键 2.选择点击设置 3.点击账户 4.点击登录选项 5.点击密码,添加密码 6.设置密码 7.使用快捷键“窗口键+l”锁屏,就会提示你输入密码

  9. 身份证验证PHP类

    PHP根据身份证号,自动获取对应的星座函数,然后自动返回对应的星座,自动返回性别,判断是否成年 <?php class IdcardAction extends Action{ // PHP根据 ...

  10. 腾讯微服务框架Tars的初体验

    最近研究了一下腾讯的微服务体系开发框架. 官方的搭建过程:https://github.com/TarsCloud/Tars/blob/master/Install.zh.md 自己填的坑: 不得不说 ...