没有多少人用莫队做吗?

蒟蒻水一波莫队

这是一道树上莫队好题。

时间复杂度(\(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. 39 (OC) 瀑布流、不规则UI

    39  (OC)  瀑布流.不规则UI

  2. 23 (OC)* 推送、APNS

    1:APNS的推送机制 2:APNS推送通知的详细工作流程 3:准备工作 4:TCP长连接 5:消息格式 6:卸载后接受不到消息 1.APNS的推送机制 首先我们看一下苹果官方给出的对ios推送机制的 ...

  3. [Advanced Python] 12 - Interview Quiz

    第一步.大扫荡复习 Resource: https://www.liaoxuefeng.com/wiki/1016959663602400/1016959735620448 IDE:https://r ...

  4. netCDF4 not installed properly - DLL load failed (netCDF4安装问题)

    环境描述:windows10 ,conda,python3.6 问题描述:netCDF4是python中用来处理地球气象数据的文件读取包,在安装完成后,from netCDF4 import Data ...

  5. Channel使用技巧

    前言 Go协程一般使用channel(通道)通信从而协调/同步他们的工作.合理利用Go协程和channel能帮助我们大大提高程序的性能.本文将介绍一些使用channel的场景及技巧 场景一,使用cha ...

  6. 不fq安装 golang tools

    go get -u -v github.com/golang/tools/go/buildutil ln -s $GOPATH/src/github.com/golang/tools $GOPATH/ ...

  7. Selenium+python操作id为动态变化的frame(iframe)

    先定位到一组frame:ele = dr.find_elements_by_tag_name('iframe')此时获得一组frame 再通过index取需要切进去的frame并取到该frame的id ...

  8. CVPR 2019 论文解读 | 小样本域适应的目标检测

    引文 ​ 最近笔者也在寻找目标检测的其他方向,一般可以继续挖掘的方向是从目标检测的数据入手,困难样本的目标检测,如检测物体被遮挡,极小人脸检测,亦或者数据样本不足的算法.这里笔者介绍一篇小样本(few ...

  9. FormatMessage将错误代码转换成对应的字符串

    // ConsoleApplication1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" int _tmain(int argc, _T ...

  10. Java 学习笔记之 异常法停止线程

    异常法停止线程: public class RealInterruptThread extends Thread { @Override public void run() { try { for ( ...