题解 CF600E 【Lomsat gelral】
没有多少人用莫队做吗?
蒟蒻水一波莫队
这是一道树上莫队好题。
时间复杂度(\(n\sqrt{n}logn\))
蒟蒻过菜,不会去掉logn的做法qaq
思路很简单:
1.dfs跑一下树上点的dfs序。
2.将树上点按dfs序进行\(\sqrt{n}\) 分块。
3.对每个点按左端点的块序号和右端点的大小排序。
inline int cmp(Node aa,Node bb)
{
return aa.ls==bb.ls?aa.r<bb.r:aa.ls<bb.ls;
}
4.开始莫队,用num[x]数组统计出现x次的颜色的序号和。转移时将原先的减去,再加上现在的。
inline void add(int x)
{
int xx=coll[x];
if(num[xx])
add(num[xx],-xx,1);
num[xx]++;
add(num[xx],xx,1);
}
inline void del(int x)
{
int xx=coll[x];
add(num[xx],-xx,1);
num[xx]--;
if(num[xx])
add(num[xx],xx,1);
}
5.将num用线段树维护最大值。
6.查找num[x]中使num[x]!=0的x最大值,并num[x]为答案。(用线段树维护)
p.s.程序理论上时间复杂度爆了,但是经过我在考场上拍的时候没有多少数据可以卡掉,并且可以卡掉这个程序的数据第二次试的时候就不会爆,所以这个程序只要评测机高兴,就不会挂。
上代码(预警,代码中含有大量无用数组)
码长:3000B
当当当当
#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
inline ll read()
{
ll f=0,x=1;char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')x=-1;ch=getchar();
}
while(ch>='0'&&ch<='9')f=(f<<1)+(f<<3)+ch-'0',ch=getchar();
return f*x;
}
ll n,col[100009],siz,cnt=0,head[100009],dfn[100009],
l[100009],r[100009],num[100009],ans=0,maxx=0,anss[100009],
coll[100009];
struct edge
{
ll to,nxt;
}e[200009];
struct Node
{
ll l,r,id,bh,col,ls,rs;
}a[100009];
struct segtree
{
ll l,r,w;
}tree[400009];
inline void adde(int a,int b)
{
cnt++;
e[cnt].nxt=head[a];
e[cnt].to=b;
head[a]=cnt;
}
inline void dfs(int x,int fa)
{
dfn[x]=++cnt;
l[cnt]=x;coll[cnt]=col[x];
a[cnt].id=x;a[cnt].l=cnt;a[cnt].col=col[x];
for(int i=head[x];~i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;
dfs(v,x);
}
r[x]=cnt;
a[dfn[x]].r=cnt;
}
inline int cmp(Node aa,Node bb)
{
return aa.ls==bb.ls?aa.r<bb.r:aa.ls<bb.ls;
}
inline void build(int l,int r,int p)
{
tree[p].l=l;tree[p].r=r;
if(l==r)
return ;
int mid=(l+r)>>1;
build(l,mid,p*2);build(mid+1,r,p*2+1);
}
inline void add(int x,int xx,int p)
{
if(tree[p].l==tree[p].r)
{
tree[p].w+=xx;
//printf("%d %d %d\n",tree[p].l,tree[p].r,tree[p].w);
return ;
}
int mid=(tree[p].l+tree[p].r)>>1;
if(x<=mid)add(x,xx,p*2);
else add(x,xx,p*2+1);
tree[p].w=tree[p*2].w+tree[p*2+1].w;
//printf("%d %d %d %d\n",tree[p].l,tree[p].r,tree[p].w,xx);
}
inline void add(int x)
{
int xx=coll[x];
//ans[num[xx]]-=x;
if(num[xx])
add(num[xx],-xx,1);
num[xx]++;
add(num[xx],xx,1);
//printf("!!!%d %d %d\n",x,xx,a[x].id);
//ans[num[xx]]+=x
//if(num[x]==maxx)ans+=x;
}
inline void del(int x)
{
int xx=coll[x];
add(num[xx],-xx,1);
num[xx]--;
//printf("!!!%d %d %d\n",x,xx,a[x].id);
if(num[xx])
add(num[xx],xx,1);
}
inline void find(int l,int r,int p)
{
if(ans)return ;
if(l<=tree[p].l&&r>=tree[p].r){
int mid=(tree[p].l+tree[p].r)>>1;
if(tree[p].l==tree[p].r){
ans=max(ans,tree[p].w);return ;
}
if(tree[p*2+1].w)find(l,r,p*2+1);
else if(tree[p*2].w)find(l,r,p*2);
return ;
}
int mid=(tree[p].l+tree[p].r)>>1;
if(r>mid)find(l,r,p*2+1);
if(l<=mid)find(l,r,p*2);
}
int main()
{
n=read();siz=sqrt(n);
build(1,n,1);
memset(head,-1,sizeof(head));
//printf("%d\n",n);
for(int i=1;i<=n;i++){
col[i]=read();
}
for(int i=1;i<=n-1;i++){
int a=read(),b=read();
adde(a,b);adde(b,a);
}
cnt=0;
dfs(1,1);
for(int i=1;i<=n;i++)
{
a[i].ls=(a[i].l+siz-1)/siz;
}
sort(a+1,a+n+1,cmp);
int l=1,r=0;
for(int i=1;i<=n;i++)
{
ans=0;
while(r<a[i].r)add(++r);
while(r>a[i].r)del(r--);
while(l<a[i].l)del(l++);
while(l>a[i].l)add(--l);
find(1,n,1);
anss[a[i].id]=ans;
//printf("ans %d %d %d %d\n",a[i].l,a[i].r,a[i].id,ans);
}
for(int i=1;i<=n;i++)printf("%lld ",anss[i]);
return 0;
}
题解 CF600E 【Lomsat gelral】的更多相关文章
- CF600E Lomsat gelral 和 CF741D Dokhtar-kosh paths
Lomsat gelral 一棵以\(1\)为根的树有\(n\)个结点,每个结点都有一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号(若有数量一样的,则求编号和). \(n \le 10^ ...
- 【学习笔记/题解】树上启发式合并/CF600E Lomsat gelral
题目戳我 \(\text{Solution:}\) 树上启发式合并,是对普通暴力的一种优化. 考虑本题,最暴力的做法显然是暴力统计每一次的子树,为了避免其他子树影响,每次统计完子树都需要清空其信息. ...
- CF600E Lomsat gelral 【线段树合并】
题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...
- CF600E Lomsat gelral (启发式合并)
You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour. Let's cal ...
- CF600E Lomsat gelral (dfs序+莫队)
题面 题解 看到网上写了很多DSU和线段树合并的题解,笔者第一次做也是用的线段树合并,但在原题赛的时候却怕线段树合并调不出来,于是就用了更好想更好调的莫队. 这里笔者就说说莫队怎么做吧. 我们可以通过 ...
- CF600E Lomsat gelral(dsu on tree)
dsu on tree跟冰茶祭有什么关系啊喂 dsu on tree的模板题 思想与解题过程 类似树链剖分的思路 先统计轻儿子的贡献,再统计重儿子的贡献,得出当前节点的答案后再减去轻儿子对答案的贡献 ...
- CF600E:Lomsat gelral(线段树合并)
Description 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. Input 第一行一个$n$.第二行$n$个数字是$c[i]$.后面$n-1$ ...
- [CF600E]Lomsat gelral
题意翻译 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 线段树合并板子题,没啥难度,注意开long long 不过这题$dsu$ $on$ $tre ...
- dsu on tree(CF600E Lomsat gelral)
题意 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. dsu on tree 用来解决子树问题 好像不能带修改?? 暴力做这个题,就是每次扫一遍子树统 ...
- cf600E. Lomsat gelral(dsu on tree)
题意 题目链接 给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和 Sol dsu on tree的裸题. 一会儿好好总结总结qwq #include<bits/stdc++.h> ...
随机推荐
- MOOC C++笔记(三):类和对象提高
第三周:类和对象提高 this指针 作用 this指针作用就是指向成员函数所作用的对象. 非静态成员函数中可以直接使用this来代表指向该函数作用的指针. 成员函数中默认有一个this指针指向当前对象 ...
- RDDs之combineByKey()
combineByKey(crateCombiner,mergeValue,mergeCombiners,partitioner) 最常用的基于Key的聚合函数,返回的类型可以和输入的类型不一样 许多 ...
- 【深度学习】Focal Loss 与 GHM——解决样本不平衡问题
Focal Loss 与 GHM Focal Loss Focal Loss 的提出主要是为了解决难易样本数量不平衡(注意:这有别于正负样本数量不均衡问题)问题.下面以目标检测应用场景来说明. 一些 ...
- ASP.NET 服务端接收Multipart/form-data文件
在网络编程过程中需要向服务器上传文件. Multipart/form-data是上传文件的一种方式. /// <summary> /// 上传工程文件 /// </summary&g ...
- Spring 梳理 - JavaConfig实战(spring MVC)-原创
目录结构 AppInitializer.java package com.jt; import org.springframework.web.servlet.support.AbstractAnno ...
- Enum枚举的使用实现
业务中涉及到的状态字段或者简单的选择项的使用. 例如: 1.定义enum枚举类. package com.yjl.enums; import java.util.Objects; public enu ...
- Nginx+PHP7.3.9 Docker镜像制作
最近因项目需要制作了多个版本的php docker镜像,制作过程可谓是一波三折,因基于yum的方式安装php的方式在安装扩展插件时很不方便,不容易找到插件对应的yum源,所以PHP在docker镜像中 ...
- 设计模式的七大原则(Java)
一.OOP三大基本特性 OOP 面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法.模型是用来反映现实世 ...
- xpath语法分享
# xpath语法: ## 使用方式: 使用//获取整个页面当中的元素,然后写标签名,然后再写谓词进行提取.比如: ``` //div[@class='abc'] ``` ## 需要注意的知识点: 1 ...
- IDEA 学习笔记之 Console显示日志大小
Console显示日志大小: IntelliJ IDEA默认的Output输出缓存区大小只有1024KB,超过大小限制的就会被清除,而且还会显示[too much output to process] ...