【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 ...
随机推荐
- iphone6 iphone6 plus 放大显示模式高分辨率模式问题
分为兼容模式和高分辨率模式. 兼容模式 当你的 app 没有提供 3x 的 LaunchImage 时,系统默认进入兼容模式,大屏幕一切按照 320 宽度渲染,屏幕宽度返回 320:然后等比例拉伸到大 ...
- 关于 Overtrue 的拼音库 overtrue/pinyin 为何 travis 为 error
什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小企业和创业者提供社会化软件研发及技术解决方案,目前最新版本为ThinkSNS+(简称TS+).Thin ...
- PJzhang:web漏洞扫描工具sitadel
猫宁!!! 参考链接:https://www.freebuf.com/sectool/194769.html 转变博客的写作思路,力求精简快捷,不浪费自己或者他人的时间. sitadel是一款精简的w ...
- [Android]XML和JSON的区别
1.定义介绍 (1).XML定义 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允 ...
- TDH-常见运维指令
1.查看cpu: cat /proc/cpuinfo | grep processor2.查看磁盘:df -h (查看磁盘使用率) df -i (查看iNode使用) fdisk -l (查看磁盘整体 ...
- Python 踩坑之旅进程篇其四一次性踩透 uid euid suid gid egid sgid的坑坑洼洼
目录 1.1 踩坑案例 1.2 填坑解法 1.3 坑位分析 1.4 技术关键字 1.5 坑后思考 下期坑位预告 代码示例支持 平台: Centos 6.3 Python: 2.7.14 代码示例: 菜 ...
- c# 基础字符串
ToLower():得到字符串的小写形式.注意字符串是不可变的,所以这些函数都不会直接改变字符串的内容,而是把修改后的字符串的值通过函数返回值的形式返回.s.ToLower()与s=s.ToLower ...
- codevs 4888 零件分组
4888 零件分组 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 现有一些棍状零件,每个零件都有 ...
- Python+Selenium与Chrome如何进行完美结合
zhuan:http://blog.51cto.com/starpoint/2102975?cid=704621 使用WebDriver在Chrome浏览器上进行测试时,需要从http://chrom ...
- 【虚拟机-网关】如何在使用应用程序网关和 Nginx 的环境下实现强制 HTTPS 跳转
背景介绍 大家在使用 Nginx 部署网站时,实现 HTTP 到 HTTPS 的强制跳转是非常容易的事情,一般可以使用rewrite 命令或者使用返回自定义 301 页面的方法对 HTTP 请求进行 ...