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 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...
随机推荐
- Halodoc使用 Apache Hudi 构建 Lakehouse的关键经验
Halodoc 数据工程已经从传统的数据平台 1.0 发展到使用 LakeHouse 架构的现代数据平台 2.0 的改造.在我们之前的博客中,我们提到了我们如何在 Halodoc 实施 Lakehou ...
- redis相关知识点
redis 的相关知识点 启动 启动代码 redis-cli -a 密码 通用命令 expire: 设置有效期 expire name 10 key key * 相关数据类型 String set:添 ...
- Solon 1.8.3 发布,云原生微服务开发框架
相对于 Spring Boot 和 Spring Cloud 的项目 启动快 5 - 10 倍 qps 高 2- 3 倍 运行时内存节省 1/3 ~ 1/2 打包可以缩小到 1/2 ~ 1/10(比如 ...
- JDBCToolsV2:利用ThreadLocal保证当前线程操作同一个数据库连接对象。
JDBCToolsV2: 利用ThreadLocal保证当前线程操作同一个数据库连接对象. package com.dgd.test; import com.alibaba.druid.poo ...
- JDBC: ThreadLocal 类
1.ThreadLocal ThreadLocal用于保存某个线程共享变量.在Java中,每个线程对象都有一个ThreadLocal<ThreadLocal,Object>,其中key就是 ...
- 方法的调用和JDK9的JShell简单使用
方法在定义完毕后,方法不会自己运行,必须被调用才能执行,我们可以在主方法main中来调用我们自己定义好的方法.在主方法中,直接写要调用的方法名字就可以调用了 public static void ma ...
- abstract,抽象修饰符
//abstract 抽象类:类由extends继承继承表现在单继承(接口可以多继承)//abstract--约束~~有人帮我们实现抽象方法,只有方法名字,没有方法实现1.不能靠new这个抽象类,只靠 ...
- Solution -「Luogu 5170」类欧几里得算法
推柿子大赛了属于是. 题目要求三个柿子,不妨分别记为: \[\begin {align} f (a, b, c, n) &= \sum \limits _{i = 0} ^{n} \lfloo ...
- 如何手写一个js工具库?同时发布到npm上
自从工作以来,写项目的时候经常需要手写一些方法和引入一些js库 JS基础又十分重要,于是就萌生出自己创建一个JS工具库并发布到npm上的想法 于是就创建了一个名为learnjts的项目,在空余时间也写 ...
- 外贸ERP系统哪些模块比较重要?得具备什么功能?
我国的外贸企业众多,涉及到多个行业,受疫情的影响,部分企业面临着极大的发展难题.而想要更好的在市场当中生存,除了要有更敏锐的市场嗅觉,也要有更大胆的创新.在外贸ERP系统的发展之下,会得到更多企业的青 ...