【dsu || 线段树合并】bzoj4756: [Usaco2017 Jan]Promotion Counting
调半天原来是dsu写不熟
Description
问对于每个奶牛来说,它的子树中有几个能力值比它大的。
Input
接下来n行为1-n号奶牛的能力值pi
接下来n-1行为2-n号奶牛的经理(树中的父亲)
Output
题目分析
做法一:dsu $O(n \log n)$
用dsu的思想来利用子树的大量重复信息,树状数组配合查询。
#include<bits/stdc++.h>
const int maxn = ;
const int maxm = ; struct node
{
int fa,tot,son;
}a[maxn];
int n,p[maxn],f[maxn],cnt[maxn],ans[maxn];
int edgeTot,head[maxn],nxt[maxm],edges[maxm]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void addedge(int u, int v)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
}
void update(int x, int c)
{
for (; x<=cnt[]; x+=(x&-x)) f[x] += c;
}
int query(int x)
{
int ret = ;
for (; x; x-=(x&-x)) ret += f[x];
return ret;
}
void dfs1(int x, int fa)
{
a[x].fa = fa, a[x].tot = , a[x].son = -;
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (v==fa) continue;
dfs1(v, x), a[x].tot += a[v].tot;
if (a[x].son==-||a[a[x].son].tot < a[v].tot) a[x].son = v;
}
}
void color(int x, int c, int del)
{
update(p[x], c);
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=a[x].fa&&edges[i]!=del)
color(edges[i], c, );
}
void dfs2(int x, bool fl)
{
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=a[x].fa&&edges[i]!=a[x].son)
dfs2(edges[i], );
if (a[x].son!=-) dfs2(a[x].son, );
color(x, , a[x].son);
ans[x] = query(p[x]-);
if (!fl) color(x, -, );
}
int main()
{
memset(head, -, sizeof head);
cnt[] = n = read();
for (int i=; i<=n; i++) p[i] = cnt[i] = read();
std::sort(cnt+, cnt+n+);
cnt[] = std::unique(cnt+, cnt+n+)-cnt-;
for (int i=; i<=n; i++)
p[i] = cnt[]+-(std::lower_bound(cnt+, cnt+cnt[]+, p[i])-cnt);
for (int i=; i<n; i++) addedge(read(), i+);
dfs1(, ), dfs2(, );
for (int i=; i<=n; i++) printf("%d\n",ans[i]);
return ;
}
做法二:线段树合并 $O(n \log n)$
暂时没写,好像常数比dsu小。
upd:写了一下发现常数(本题)确实比dsu小。
线段树合并的思想不难理解,就是仿照堆的合并思路处理,原理则是基于线段树结构相同。
在动态开点的前提下,时间空间复杂度都是$O(n\log n)$的。
#include<bits/stdc++.h>
const int maxn = ;
const int maxm = ;
const int maxNode = ; struct node
{
int l,r,val;
}a[maxNode];
int n,tot;
int rt[maxn],p[maxn],cnt[maxn],ans[maxn];
int edgeTot,head[maxn],nxt[maxm],edges[maxm]; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void addedge(int u, int v)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
}
void write(int x){if (x/) write(x/);putchar(''+x%);}
void merge(int &u, int v)
{
if (!v) return;
if (!u) u = v;
else{
a[u].val += a[v].val;
merge(a[u].l, a[v].l);
merge(a[u].r, a[v].r);
}
}
int query(int rt, int l, int r, int c)
{
if (!rt) return ;
if (r <= c) return a[rt].val;
int mid = (l+r)>>, ret = query(a[rt].l, l, mid, c);
if (mid < c) ret += query(a[rt].r, mid+, r, c);
return ret;
}
void update(int &rt, int l, int r, int c)
{
if (!rt) rt = ++tot;
++a[rt].val;
if (l==r) return;
int mid = (l+r)>>;
if (c <= mid) update(a[rt].l, l, mid, c);
else update(a[rt].r, mid+, r, c);
}
void dfs(int x)
{
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
dfs(v), merge(rt[x], rt[v]);
}
ans[x] = query(rt[x], , cnt[], p[x]);
update(rt[x], , cnt[], p[x]);
}
int main()
{
memset(head, -, sizeof head);
n = read();
for (int i=; i<=n; i++) p[i] = cnt[i] = read();
for (int i=; i<n; i++) addedge(read(), i+);
std::sort(cnt+, cnt+n+);
cnt[] = std::unique(cnt+, cnt+n+)-cnt-;
for (int i=; i<=n; i++)
p[i] = cnt[]+-(std::lower_bound(cnt+, cnt+cnt[]+, p[i])-cnt);
dfs();
for (int i=; i<=n; i++) write(ans[i]), putchar('\n');
return ;
}
END
【dsu || 线段树合并】bzoj4756: [Usaco2017 Jan]Promotion Counting的更多相关文章
- [BZOJ4756][Usaco2017 Jan]Promotion Counting 树状数组
4756: [Usaco2017 Jan]Promotion Counting Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 305 Solved: ...
- BZOJ4756: [Usaco2017 Jan]Promotion Counting(线段树合并)
题意 题目链接 Sol 线段树合并板子题 #include<bits/stdc++.h> using namespace std; const int MAXN = 400000, SS ...
- [BZOJ4756] [Usaco2017 Jan]Promotion Counting(线段树合并)
传送门 此题很有意思,有多种解法 1.用天天爱跑步的方法,进入子树的时候ans-query,出去子树的时候ans+query,query可以用树状数组或线段树来搞 2.按dfs序建立主席树 3.线段树 ...
- bzoj4756 [Usaco2017 Jan]Promotion Counting
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4756 [题解] dsu on tree,树状数组直接上 O(nlog^2n) # inclu ...
- 线段树合并 || 树状数组 || 离散化 || BZOJ 4756: [Usaco2017 Jan]Promotion Counting || Luogu P3605 [USACO17JAN]Promotion Counting晋升者计数
题面:P3605 [USACO17JAN]Promotion Counting晋升者计数 题解:这是一道万能题,树状数组 || 主席树 || 线段树合并 || 莫队套分块 || 线段树 都可以写..记 ...
- BZOJ[Usaco2017 Jan]Promotion Counting——线段树合并
题目描述 The cows have once again tried to form a startup company, failing to remember from past experie ...
- 2018.08.27 [Usaco2017 Jan]Promotion Counting(线段树合并)
描述 The cows have once again tried to form a startup company, failing to remember from past experienc ...
- bzoj 4756 [Usaco2017 Jan]Promotion Counting——线段树合并
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4756 线段树合并裸题.那种返回 int 的与传引用的 merge 都能过.不知别的题是不是这 ...
- 【bzoj 4756】[Usaco2017 Jan] Promotion Counting
Description The cows have once again tried to form a startup company, failing to remember from past ...
随机推荐
- 查看java 版本
执行 java -version 命令,如下图所示如果没有明确显示位数的,则说明是32位 C:\MyTools\jdk1.7.0\bin>java -version java version & ...
- UML工具 PlantUML SequenceDiagram
- SpringBoot用户CRUD
1.准备 http://start.spring.io/ 这里地址去直接生成你需要的项目信息,如何你本身ide以及集成了springboot 那么可以直接生成项目信息 需要的知识:java,sprin ...
- Jquery树形控件 $.fn.zTree.init
https://www.cnblogs.com/jin-/p/4646202.html asp.net 树形控件 $.fn.zTree.init 在网页中通过jquery脚本来构筑树形控件将是一个不错 ...
- Ubuntu14.04 使用scp远程传输命令进行服务器文件互传
1.将另一个服务器上的文件拷贝到本地 sudo scp host_name@host_ip:/home/aaa/bbb /ccc/ddd/bbb 上面命令的意思是将远程服务器/home/aaa/目录下 ...
- 自定义Spring Security的身份验证失败处理
1.概述 在本快速教程中,我们将演示如何在Spring Boot应用程序中自定义Spring Security的身份验证失败处理.目标是使用表单登录方法对用户进行身份验证. 2.认证和授权(Authe ...
- 数据结构之Hyperloglog
前置知识 调和平均数 通常我们求一堆数的平均数 就是把一堆数加起来除以这堆数的数量,如 x1, x2, x3, x4, .... ,xn的平均数 H = (x1 + x2 + x3 + x4 + xn ...
- yum指令之修复
折腾着搞 openvpn 网站服务器 yum指令 出了点问题 ------------------------------------------------------------ [root@cl ...
- java获取服务器一些信息的方法
request.getServletContext().getRealPath("/") 获取项目所在服务器的全路径,如:D:\Program Files\apache-tomca ...
- spring之控制反转
IOC (Inversion of Control) 控制反转 我的理解:将创建对象的控制权从代码本身转交给了外部容器(spring容器). 1.将组件对象(业务对象)的控制权从代码本身转移到外部容器 ...