CF600E Lomsat gelral (dfs序+莫队)
题面
题解
看到网上写了很多DSU和线段树合并的题解,笔者第一次做也是用的线段树合并,但在原题赛的时候却怕线段树合并调不出来,于是就用了更好想更好调的莫队。
这里笔者就说说莫队怎么做吧。
我们可以通过 dfs 序把点都拍到序列上,然后每个点的主导编号和就相当于询问一段区间的主导编号和,并且这样的询问刚好 n 个。
那么维护两个数组和一个变量
- C
[
i
]
C[i]
C[i]:第
i
i
i 种颜色的出现次数
- S
m
[
i
]
Sm[i]
Sm[i]:出现
i
i
i 次的颜色编号和
- a
n
s
ans
ans:出现的最多次数是几次(即实际的答案是
S
m
[
a
n
s
]
Sm[ans]
Sm[ans],这样方便维护些)
当我们的序列中新加入一个点时(我们已经开始跑莫队了),设这个点的颜色为
c
o
l
col
col ,那么
C
[
c
o
l
]
C[col]
C[col] 很好维护吧,
S
m
[
.
.
.
]
Sm[...]
Sm[...] 也很好维护吧,那么我们需要证明一个结论:
a
n
s
ans
ans 每次变动的幅度最多为 1。
其实很好证,由于每次
C
[
c
o
l
]
C[col]
C[col] 最多改 1,因此
S
m
[
.
.
.
]
Sm[...]
Sm[...] 只在长度为 2 的范围内有变动,其中一个清零的话,另一个肯定会有值,而
a
n
s
ans
ans 的值只取决于最大的有值的
S
m
[
.
.
.
]
Sm[...]
Sm[...] ,因此由于最大的
S
m
Sm
Sm 最多变动 1,所以
a
n
s
ans
ans 也最多变动 1。在脑袋里模拟一下也会理解的。
具体怎么操作可以看代码的
i
n
s
(
)
ins()
ins() 和
d
e
l
(
)
del()
del() 函数。
CODE
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define LL long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) : (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return x * f;
}
const int MOD = 1000000007;
int n,m,i,j,s,o,k,sq;
vector<int> g[MAXN];
int dfn[MAXN],rr[MAXN],cnt,id[MAXN];
int cl[MAXN];
void dfs(int x,int fa) {
dfn[x] = ++ cnt; id[cnt] = x;
for(int i = 0;i < (int)g[x].size();i ++) {
if(g[x][i] != fa) {
dfs(g[x][i],x);
}
}
rr[x] = cnt;
return ;
}
struct it{
int l,r,id;
}q[MAXN];
bool cmp(it a,it b) {
if(a.l/sq != b.l/sq) return a.l < b.l;
return a.r < b.r;
}
int L,R,c[MAXN],ans;
LL sm[MAXN],as[MAXN];
void ins(int x) { // x 是点编号
int col = cl[x];
sm[c[col]] -= col;
c[col] ++;
sm[c[col]] += col;
if(sm[ans+1] > 0) ans ++;
else if(!sm[ans]) ans --;
return ;
}
void del(int x) {
int col = cl[x];
sm[c[col]] -= col;
c[col] --;
sm[c[col]] += col;
if(sm[ans+1] > 0) ans ++;
else if(!sm[ans]) ans --;
return ;
}
int main() {
n = read();
sq = (int)sqrt((DB)n);
for(int i = 1;i <= n;i ++) cl[i] = read();
for(int i = 1;i < n;i ++) {
s = read();o = read();
g[s].push_back(o);
g[o].push_back(s);
}
dfs(1,0);
for(int i = 1;i <= n;i ++) {
q[i].id = i;
q[i].l = dfn[i];q[i].r = rr[i];
}
sort(q + 1,q + 1 + n,cmp);
L = 1,R = 0;
for(int i = 1;i <= n;i ++) {
int l = q[i].l,r = q[i].r;
while(L > l) ins(id[-- L]);
while(R < r) ins(id[++ R]);
while(L < l) del(id[L ++]);
while(R > r) del(id[R --]);
as[q[i].id] = sm[ans];
}
for(int i = 1;i <= n;i ++) {
printf("%lld ",as[i]);
}ENDL;
return 0;
}
CF600E Lomsat gelral (dfs序+莫队)的更多相关文章
- hdu 4358 Boring counting dfs序+莫队+离散化
Boring counting Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 98304/98304 K (Java/Others) ...
- hdu 4358 Boring counting 离散化+dfs序+莫队算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight ...
- Codeforces 375D - Tree and Queries(dfs序+莫队)
题目链接:http://codeforces.com/contest/351/problem/D 题目大意:n个数,col[i]对应第i个数的颜色,并给你他们之间的树形关系(以1为根),有m次询问,每 ...
- Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)
题目链接 Tree and Queries 题目大意 给出一棵树和每个节点的颜色.每次询问$vj, kj$ 你需要回答在以$vj$为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少 ...
- HDU 4358 Boring counting dfs序+莫队算法
题意:N个节点的有根树,每个节点有一个weight.有Q个查询,问在以u为根的子树中,有恰好出现了K次的weight有多少种. 这是第一次写莫队算法,之前也只是偶有耳闻. 看了别人的代码打的,还是贴上 ...
- codeforces 375D . Tree and Queries 启发式合并 || dfs序+莫队
题目链接 一个n个节点的树, 每一个节点有一个颜色, 1是根节点. m个询问, 每个询问给出u, k. 输出u的子树中出现次数大于等于k的颜色的数量. 启发式合并, 先将输入读进来, 然后dfs完一个 ...
- CF600E Lomsat gelral(dsu on tree)
dsu on tree跟冰茶祭有什么关系啊喂 dsu on tree的模板题 思想与解题过程 类似树链剖分的思路 先统计轻儿子的贡献,再统计重儿子的贡献,得出当前节点的答案后再减去轻儿子对答案的贡献 ...
- CF600E Lomsat gelral 和 CF741D Dokhtar-kosh paths
Lomsat gelral 一棵以\(1\)为根的树有\(n\)个结点,每个结点都有一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号(若有数量一样的,则求编号和). \(n \le 10^ ...
- CF600E Lomsat gelral 【线段树合并】
题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...
随机推荐
- python中f'{}'用法
python3.6增加的方法,字符串定义以f开头,可以使用{}包裹变量,方便字符串的定义. 有些时候很懒,碰到写的比较清晰的就直接搬运:https://blog.csdn.net/weixin_387 ...
- Linux系列之安装中文字体
Linux系统安装中文字体 拷贝字体文件至Linux 从windows电脑的C:\Windows\fonts复制字体文件上传至Linux服务器新建的目录下 复制ttc.ttf文件至Linux服务器字体 ...
- .NET中检测文件是否被其他进程占用
更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 一.检测文件是否被进程占用的几种方式 在.NET中主要有以下方式进行检测文件是否被进程占用的几种方式: 通过直接打开文件等 ...
- 一文看完vue3的变化之处
在通读了vue的官网文档后,我记录下了如下这些相对于2.x的变化之处. 1.创建应用实例的变化 之前一般是这样: let app = new Vue({ // ...一些选项 template: '' ...
- DTCC 干货分享:Real Time DaaS - 面向TP+AP业务的数据平台架构
2021年10月20日,Tapdata 创始人唐建法(TJ)受邀出席 DTCC 2021(中国数据库技术大会),并在企业数据中台设计与实践专场上,发表主旨演讲"Real Time Daa ...
- Windows对拍系统
有个东西可以帮助对拍,告诉你两个程序的输出哪不一样(但是无法得知错误位置,聊胜于无吧) 一.打开计算机 二.在上方输入$cmd$,摁下回车 三.弹出对话窗如下,输入$fc +$空格,输入两个需要比较 ...
- 【cartographer_ros】六: 发布和订阅路标landmark信息
上一节介绍了陀螺仪Imu传感数据的订阅和发布. 本节会介绍路标Landmark数据的发布和订阅.Landmark在cartographer中作为定位的修正补充,避免定位丢失. 这里着重解释一下Land ...
- Ant Design Vue 走马灯实现单页多张图片轮播
最近的项目有个需求是,这种单页多图一次滚动一张图片的轮播效果,项目组件库是antd 然而用了antd的走马灯是这样子的 我们可以看到官网给的api是没有这种功能,百度上也多是在css上动刀,那样也就毕 ...
- springboot和mybatis 配置多数据源
主数据源(由于代码没有办法复制的原因,下面图片和文字不一致) package com.zhianchen.mysqlremark.toword.config;import com.zaxxer.hik ...
- vue 调用nginx服务跨越的问题
server { listen 80; server_name api.xxxx.com; add_header Access-Control-Allow-Origin '*' ; proxy_set ...