线段树合并 || 树状数组 || 离散化 || BZOJ 4756: [Usaco2017 Jan]Promotion Counting || Luogu P3605 [USACO17JAN]Promotion Counting晋升者计数
题面:P3605 [USACO17JAN]Promotion Counting晋升者计数
题解:这是一道万能题,树状数组 || 主席树 || 线段树合并 || 莫队套分块 || 线段树 都可以写。。记得离散化
线段树合并版:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=(1e5)+;
int N,num_edge=,edge_head[maxn],W[maxn],lsh_cnt=,num_treenode=;
int root[maxn],ans[maxn],u;
struct A_{int id,data;}A[maxn];
inline bool cmp(const A_&a,const A_&b){return a.data<b.data;}
struct Edge{int to,nx;}edge[maxn];
inline void Add_edge(int from,int to){
edge[++num_edge].nx=edge_head[from];
edge[num_edge].to=to;
edge_head[from]=num_edge;
return;
}
struct Tree{int lc,rc,l,r,cnt;}t[maxn*];
inline void Build(int x,int l,int r,int q){
t[x].l=l;t[x].r=r;int mid=(l+r)>>;
if(l==r&&l==q){
t[x].cnt=;
return;
}
if(q<=mid)Build(t[x].lc=++num_treenode,l,mid,q);
else Build(t[x].rc=++num_treenode,mid+,r,q);
t[x].cnt=t[t[x].lc].cnt+t[t[x].rc].cnt;
return;
}
inline int Merge(int u,int v){
if(!u)return v;
if(!v)return u;
int l=t[u].l,r=t[u].r;
if(l==r){
t[u].cnt+=t[v].cnt;
return u;
}
t[u].lc=Merge(t[u].lc,t[v].lc);
t[u].rc=Merge(t[u].rc,t[v].rc);
t[u].cnt=t[t[u].lc].cnt+t[t[u].rc].cnt;
return u;
}
inline void Query(int g,int x,int ql,int qr){
int l=t[x].l,r=t[x].r,mid=(l+r)>>,lc=t[x].lc,rc=t[x].rc;
if(x==)return;
if(ql<=l&&r<=qr){
ans[g]+=t[x].cnt;
return;
}
if(ql<=mid)Query(g,lc,ql,qr);
if(qr>mid) Query(g,rc,ql,qr);
return;
}
inline void Dfs(int x){
for(int i=edge_head[x];i;i=edge[i].nx){
int y=edge[i].to;
Dfs(y);
root[x]=Merge(root[x],root[y]);
}
if(W[x]+>lsh_cnt)ans[x]=;
else Query(x,root[x],W[x]+,lsh_cnt);
return;
}
int main(){
scanf("%d",&N);
for(int i=;i<=N;i++){
scanf("%d",&A[i].data);
A[i].id=i;
}
sort(A+,A+N+,cmp);
W[A[].id]=++lsh_cnt;
for(int i=;i<=N;i++)
if(A[i].data!=A[i-].data)W[A[i].id]=++lsh_cnt;
else W[A[i].id]=lsh_cnt;
for(int i=;i<=N;i++){
scanf("%d",&u);
Add_edge(u,i);
}
for(int i=;i<=N;i++)Build(root[i]=++num_treenode,,lsh_cnt+,W[i]);
Dfs();
for(int i=;i<=N;i++)printf("%d\n",ans[i]);
return ;
}
树状数组版:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define re register
using namespace std;
inline int rd(){
int x=;char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x;
}
const int maxn=1e5;
int N,P[maxn+],cnt=,num_edge=,edge_head[maxn+],F,C[maxn+];
ll ans[maxn+];
struct Edge{
int to,nx;
}edge[maxn+];
struct Node{
int x,id;
}A[maxn+];
inline bool cmp(const Node&a,const Node&b){
if(a.x<b.x)return ;
return ;
}
inline int Find(int x){
re ll ans=;
for(;x<=cnt;x+=x&(-x))ans+=C[x];
return ans;
}
inline void Update(int x){
for(;x>;x-=x&(-x))C[x]++;
return;
}
inline void Dfs(int x){
ans[x]-=Find(P[x]);
for(re int i=edge_head[x];i;i=edge[i].nx) Dfs(edge[i].to);
ans[x]+=Find(P[x]);
Update(P[x]);
return;
}
int main(){
N=rd();
for(re int i=;i<=N;i++){
A[i].x=rd();
A[i].id=i;
}
sort(A+,A+N+,cmp);
for(re int i=;i<=N;i++){
if(i==||A[i].x!=A[i-].x)cnt++;
P[A[i].id]=cnt;
}
for(re int i=;i<=N;i++){
scanf("%d",&F);
edge[++num_edge].nx=edge_head[F];
edge[num_edge].to=i;
edge_head[F]=num_edge;
}
Dfs();
for(re int i=;i<=N;i++)printf("%lld\n",ans[i]);
return ;
}
By:AlenaNuna
线段树合并 || 树状数组 || 离散化 || BZOJ 4756: [Usaco2017 Jan]Promotion Counting || Luogu P3605 [USACO17JAN]Promotion Counting晋升者计数的更多相关文章
- bzoj 4756: [Usaco2017 Jan]Promotion Counting【dfs+树状数组】
思路还是挺好玩的 首先简单粗暴的想法是dfs然后用离散化权值树状数组维护,但是这样有个问题就是这个全局的权值树状数组里并不一定都是当前点子树里的 第一反应是改树状数组,但是显然不太现实,但是可以这样想 ...
- bzoj 4756 [Usaco2017 Jan]Promotion Counting——线段树合并
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4756 线段树合并裸题.那种返回 int 的与传引用的 merge 都能过.不知别的题是不是这 ...
- BZOJ 4756 [Usaco2017 Jan]Promotion Counting(线段树合并)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4756 [题目大意] 给出一棵树,对于每个节点,求其子树中比父节点大的点个数 [题解] ...
- POJ 2299 【树状数组 离散化】
题目链接:POJ 2299 Ultra-QuickSort Description In this problem, you have to analyze a particular sorting ...
- hdu4605 树状数组+离散化+dfs
Magic Ball Game Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- BZOJ_5055_膜法师_树状数组+离散化
BZOJ_5055_膜法师_树状数组+离散化 Description 在经历过1e9次大型战争后的宇宙中现在还剩下n个完美维度, 现在来自多元宇宙的膜法师,想偷取其中的三个维度为伟大的长者续秒, 显然 ...
- 树状数组 P3605 [USACO17JAN]Promotion Counting晋升者计数
P3605 [USACO17JAN]Promotion Counting晋升者计数 题目描述 奶牛们又一次试图创建一家创业公司,还是没有从过去的经验中吸取教训--牛是可怕的管理者! 为了方便,把奶牛从 ...
- BZOJ.3653.谈笑风生(长链剖分/线段树合并/树状数组)
BZOJ 洛谷 \(Description\) 给定一棵树,每次询问给定\(p,k\),求满足\(p,a\)都是\(b\)的祖先,且\(p,a\)距离不超过\(k\)的三元组\(p,a,b\)个数. ...
- LightOJ 1085(树状数组+离散化+DP,线段树)
All Possible Increasing Subsequences Time Limit:3000MS Memory Limit:65536KB 64bit IO Format: ...
随机推荐
- [Python设计模式] 第26章 千人千面,内在共享——享元模式
github地址:https://github.com/cheesezh/python_design_patterns 背景 有6个客户想做产品展示网站,其中3个想做成天猫商城那样的"电商风 ...
- Docker配置参考
Docker配置参考 一.参数列表 参考网址:https://docs.docker.com/engine/reference/commandline/dockerd/#options Usage: ...
- Keras/Tensorflow选择GPU/CPU运行
首先,导入os,再按照PCI_BUS_ID顺序,从0开始排列GPU, import os os.environ["CUDA_DEVICE_ORDER"] = "PCI_B ...
- iOS 内购讲解
一.总说内购的内容 1.协议.税务和银行业务 信息填写 2.内购商品的添加 3.添加沙盒测试账号 4.内购代码的具体实现 5.内购的注意事项 二.协议.税务和银行业务 信息填写 2.1.协议.税务和银 ...
- 【Python】解析Python的缩进规则
Python中的缩进(Indentation)决定了代码的作用域范围.这一点和传统的c/c++有很大的不同(传统的c/c++使用花括号花括号{}符决定作用域的范围:python使用缩进空格来表示作用域 ...
- windows上RSA密钥生成和使用
一,下载安装windows平台openssl密钥生成工具,执行安装目录bin下的"openssl.exe",执行后弹出命令窗口如下 运行 二,生成私钥 输入"genrsa ...
- 看雪CTF第八题
IDA查看Exports有3个TlsCallback 只有TlsCallback_2有用 其中创建6个线程用于代码动态解码smc 只有前三个线程有用 分别对check_part1,check_part ...
- linux的挂载的问题,重启后就挂载就没有了
我用fdisk命令,分一个/dev/sda6出来,然后用mkfs格式化为ext3,然后挂载到根目录下的PPP文件夹中,挂载是成功了,但是用reboot和shutdown重启或关机后挂载就没有了 要修改 ...
- js 时间戳转时间工具类 js时间戳与时间互转
/** * 时间戳格式化函数 * @param {string} format 格式 * @param {int} timestamp 要格式化的时间 默认为当前时间 * @return {strin ...
- IntelliJ IDEA(2018)安装和破解
IDEA 全称 IntelliJ IDEA,是Java语言开发的集成环境,IntelliJ在业界被公认为最好的java开发工具之一,尤其在智能代码助手.代码自动提示.重构.J2EE支持.各类版本工具( ...