没有多少人用莫队做吗?

蒟蒻水一波莫队

这是一道树上莫队好题。

时间复杂度(\(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】的更多相关文章

  1. CF600E Lomsat gelral 和 CF741D Dokhtar-kosh paths

    Lomsat gelral 一棵以\(1\)为根的树有\(n\)个结点,每个结点都有一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号(若有数量一样的,则求编号和). \(n \le 10^ ...

  2. 【学习笔记/题解】树上启发式合并/CF600E Lomsat gelral

    题目戳我 \(\text{Solution:}\) 树上启发式合并,是对普通暴力的一种优化. 考虑本题,最暴力的做法显然是暴力统计每一次的子树,为了避免其他子树影响,每次统计完子树都需要清空其信息. ...

  3. CF600E Lomsat gelral 【线段树合并】

    题目链接 CF600E 题解 容易想到就是线段树合并,维护每个权值区间出现的最大值以及最大值位置之和即可 对于每个节点合并一下两个子节点的信息 要注意叶子节点信息的合并和非叶节点信息的合并是不一样的 ...

  4. CF600E Lomsat gelral (启发式合并)

    You are given a rooted tree with root in vertex 1. Each vertex is coloured in some colour. Let's cal ...

  5. CF600E Lomsat gelral (dfs序+莫队)

    题面 题解 看到网上写了很多DSU和线段树合并的题解,笔者第一次做也是用的线段树合并,但在原题赛的时候却怕线段树合并调不出来,于是就用了更好想更好调的莫队. 这里笔者就说说莫队怎么做吧. 我们可以通过 ...

  6. CF600E Lomsat gelral(dsu on tree)

    dsu on tree跟冰茶祭有什么关系啊喂 dsu on tree的模板题 思想与解题过程 类似树链剖分的思路 先统计轻儿子的贡献,再统计重儿子的贡献,得出当前节点的答案后再减去轻儿子对答案的贡献 ...

  7. CF600E:Lomsat gelral(线段树合并)

    Description 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. Input 第一行一个$n$.第二行$n$个数字是$c[i]$.后面$n-1$ ...

  8. [CF600E]Lomsat gelral

    题意翻译 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. 线段树合并板子题,没啥难度,注意开long long 不过这题$dsu$ $on$ $tre ...

  9. dsu on tree(CF600E Lomsat gelral)

    题意 一棵树有n个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和. dsu on tree 用来解决子树问题 好像不能带修改?? 暴力做这个题,就是每次扫一遍子树统 ...

  10. cf600E. Lomsat gelral(dsu on tree)

    题意 题目链接 给出一个树,求出每个节点的子树中出现次数最多的颜色的编号和 Sol dsu on tree的裸题. 一会儿好好总结总结qwq #include<bits/stdc++.h> ...

随机推荐

  1. 如何使用WordPress搭建个人博客

    目录 如何使用WordPress搭建个人博客 一.在安装Linux服务器管理工具WDCP面板 二.在WDCP面板创建一个站点 二.上传博客程序到服务器 @(如何使用WordPress搭建个人博客) 如 ...

  2. [Pandas] 02 - Tutorial of NumPy

    Ref: NumPy 教程 这里主要是查缺补漏一些常用方法. 初步认识 矩阵常见知识点 矩阵操作 Ref: [Python] 01 - Number and Matrix[总结过一部分] 一.矩阵 ( ...

  3. 在linux服务器上装svn版本管理,自动部署代码到web项目

    在linux服务器上装svn版本管理,自动部署代码到项目 1.安装svn服务器端  yum install subversion   从镜像下载安装svn服务器端 中间会提示是否ok,输入y,确认  ...

  4. SpringCloud之Turbine

    [前面的话]书接上文,本文的某些知识依赖我的上一篇SpringCLoud的文章:SpringCloud之Feign,如果没有看过可以先移步去看一下.前文提到了hystrix的应用,以及hystrix的 ...

  5. springboot之全局处理统一返回

    springboot之全局处理统一返回 简介 在REST风格的开发中,避免通常会告知前台返回是否成功以及状态码等信息.这里我们通常返回的时候做一次util的包装处理工作,如:Result类似的类,里面 ...

  6. Scala Data Structure

    Arrays Array 固定长度:ArrayBuffer 可变长度 arr.toBuffer, buf.toArray 初始化是不要使用 new 使用 () 访问元素 使用 for (elem &l ...

  7. 我用阿里云的虚拟云主机,也能配置https加密吗?

    我用阿里云的虚拟云主机,也能配置https加密吗?答案是YES. 整个过程比想象中还要简单,都是一些基本的配置,虚拟主机 Web托管都可以很容易的搞定https. 首先我们要了解一下,阿里云是怎么支持 ...

  8. MySQL在Linux系统环境的安装和无主机登录配置

           将mysql 安装在单个Linux系统主机,并配置本地或远程(此处可仅单指局域状态下的环境)的无主机登录.谨记的是:操作完mysql 设置时,需以flush privileges进行权限 ...

  9. RBD 基本使用 - Storage6

    块存储管理系列文章 (1)RBD 基本使用 - Storage6 (2)iSCSI 网关管理 (3)使用 librbd 将虚拟机运行在 Ceph RBD (4)RBD Mirror 容灾 Ceph 块 ...

  10. python爬虫添加请求头和请求主体

    添加头部信息有两种方法 1.通过添加urllib.request.Request中的headers参数 #先把要用到的信息放到一个字典中 headers = {} headers['User-Agen ...