[COGS 1535] [ZJOI2004]树的果实 树状数组+桶

我们用树状数组做差就可以解决一切问题,我用桶排并用此来表示出第几大就可以直接求前缀和了

#include<cstdio>
#include<algorithm>
#define MAXN 100010
using namespace std;
inline int read()
{
   int sum=0;
   char ch=getchar();
   while(ch<‘0‘||ch>‘9‘)ch=getchar();
   while(ch>=‘0‘&&ch<=‘9‘)
   {
     sum=(sum<<1)+(sum<<3)+ch-‘0‘;
     ch=getchar();
   }
   return sum;
}
int P[MAXN],H[MAXN];
int n,m;
struct VIA
{
  int to,next;
}c[MAXN];
int head[MAXN],t;
inline void add(int x,int y)
{
  c[++t].to=y;
  c[t].next=head[x];
  head[x]=t;
}
inline int sum_H(int x)
{
  int sum=0;
  while(x>0) sum+=H[x],x-=x&(-x);
  return sum;
}
inline int sum_P(int x)
{
  int sum=0;
  while(x>0) sum+=P[x],x-=x&(-x);
  return sum;
}
inline void ins_P(int x,int key)
{
  while(x<=n) P[x]+=key,x+=x&(-x);
}
inline void ins_H(int x,int key)
{
  while(x<=n) H[x]+=key,x+=x&(-x);
}
int a[MAXN],pos[MAXN];
int Ans[MAXN][3];
int comp(const int x,const int y)
{
  return a[x]>a[y];
}
inline void Init()
{
  scanf("%d",&n);
  for(int i=2,x;i<=n;i++)x=read(),add(x,i);
  for(int i=1;i<=n;i++)a[i]=read(),pos[i]=i;
  sort(pos+1,pos+n+1,comp);
  for(int i=1;i<=n;i++)a[pos[i]]=i;
}
void dfs(int x)
{
  ins_H(a[x],1);
  int y=sum_H(a[x]-1);
  Ans[x][2]=sum_P(a[x]-1);
  ins_P(a[x],1);
  for(int i=head[x];i;i=c[i].next)
   dfs(c[i].to);
  Ans[x][1]=sum_H(a[x]-1)-y;
  ins_P(a[x],-1);
  Ans[x][0]=a[x]-1-Ans[x][1];
}
inline void work()
{
  dfs(1);
  for(int i=1;i<=n;i++)
   printf("%d %d %d\n",Ans[i][1],Ans[i][0],Ans[i][2]);
}
int main()
{
  Init();
  work();
  return 0;
}
时间: 2024-10-09 22:45:49

[COGS 1535] [ZJOI2004]树的果实 树状数组+桶的相关文章

[bzoj3155]Preprefix sum(树状数组)

3155: Preprefix sum Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 1183  Solved: 546[Submit][Status][Discuss] Description Input 第一行给出两个整数N,M.分别表示序列长度和操作个数 接下来一行有N个数,即给定的序列a1,a2,....an 接下来M行,每行对应一个操作,格式见题目描述 Output 对于每个询问操作,输出一行,表示所询问的SSi的值. Sample In

HDU 1166 —— 敌兵布阵 【树状数组 or 线段树】

http://acm.hdu.edu.cn/showproblem.php?pid=1166 需求: 1.点修改 2.区间求和 标准的BIT(二叉索引树,又名树状数组)问题,当然也可以用最基础的仅支持“点修改”的线段树来解决! 线段树版本: #include <cstdio> #include <iostream> #define INF 0x3f3f3f3f using namespace std; const int MAXN = 65536 + 5; // 65536 是最小

二分索引树与线段树分析

二分索引树是一种树状数组,其全名为Binary Indexed Tree.二分索引树可以用作统计作用,用于计某段连续区间中的总和,并且允许我们动态变更区间中存储的值.二分索引树和线段树非常相似,二者都享有相同的O(log2(n))时间复杂度的更新操作和O(log2(n))时间复杂度的查询操作,区别在于二分索引树更加简洁高效,而线段树则较冗杂低效,原因在于对二分索引树的操作中是使用了计算机中整数存储的特性来进行加速,而线段树中由于使用的是比较操作,因此性能不及二分索引树.那么为什么我们不抛弃线段树

[COGS 257]动态排名系统 树状数组套主席树

主席树就是所谓可持久化线段树.目前只会打区间k值操作. 那么带修改的呢?因为主席树目的上也是搞前缀和,所以类比数组操作,套一个树状数组就可以了. 谨以此纪念此类型树套树入门 #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define N 51000 #include<

【转】关于LIS和一类可以用树状数组优化的DP 预备知识

原文链接 http://www.cnblogs.com/liu-runda/p/6193690.html 预备知识 DP(Dynamic Programming):一种以无后效性的状态转移为基础的算法,我们可以将其不严谨地先理解为递推.例如斐波那契数列的递推求法可以不严谨地认为是DP.当然DP的状态也可以是二维/三维的,某一维的含义也不仅仅是指某个数列的第几项. 树状数组(BIT or fenwick tree):一种高效地动态维护一个序列并动态求取前缀和的数据结构.修改某个元素/求一次前缀和的

[BZOJ 2141][国家集训队 2011]排队 树状数组套平衡树

这道题也就是一个动态逆序对嘛,本质上就是个查询区间排名 刚刚打了一道 [CQOI 2011]动态逆序对  用的线段树套平衡树,代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; #define pos(i,a,b) for(int i=(a);i<=(b);i++) #define N 101000 #include<cstdlib> #def

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

(POJ 3067) Japan (慢慢熟悉的树状数组)

Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29295   Accepted: 7902 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coas

【二维树状数组】See you~

https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A x y n1 :给格点(x,y)的值加n1 D x y n1: 给格点(x,y)的值减n1,如果现在格点的值不够n1,把格点置0 M x1 y1 x2 y2:(x1,y1)移动给(x2,y2)n1个 S x1 y1 x2 y2 查询子矩阵的和 [思路] 当然是二维树状数组 但是一定要注意:lowbi