一个显然的dp是设f[i][j]为i子树内权值<=j时的答案,则f[i][j]=Σf[son][j],f[i][a[i]]++,f[i][a[i]+1~n]对其取max。这样是可以线段树合并的,但实在太弱了不太会。

  另一种做法是考虑扩展经典的单调队列优化LIS的做法,维护子树内答案为k时最小的最大值,用平衡树维护,在父亲处启发式合并,然后将父亲处权值插入即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,a[N],b[N],fa[N],p[N],root[N],t,cnt;
struct data{int to,nxt;
}edge[N<<];
struct data2{int x,p,ch[],s;
}tree[N<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void up(int k){tree[k].s=tree[lson].s+tree[rson].s+;}
void move(int &k,int p)
{
int t=tree[k].ch[p];
tree[k].ch[p]=tree[t].ch[!p],tree[t].ch[!p]=k,up(k),up(t),k=t;
}
void ins(int &k,int x)
{
if (k==) {k=++cnt;tree[k].x=x,tree[k].p=rand(),tree[k].s=;return;}
tree[k].s++;
if (tree[k].x<x) {ins(rson,x);if (tree[rson].p>tree[k].p) move(k,);}
else {ins(lson,x);if (tree[lson].p>tree[k].p) move(k,);}
}
void del(int &k,int x)
{
if (tree[k].x==x)
{
if (lson==||rson==) {k=lson|rson;return;}
if (tree[lson].p>tree[rson].p) move(k,),del(rson,x);
else move(k,),del(lson,x);
}
else if (tree[k].x<x) del(rson,x);
else del(lson,x);
up(k);
}
int qrank(int k,int x)
{
if (!k) return ;
if (tree[k].x>=x) return qrank(lson,x);
else return qrank(rson,x)+tree[lson].s+;
}
int find(int k,int x)
{
if (tree[lson].s+==x) return tree[k].x;
if (tree[lson].s+>x) return find(lson,x);
else return find(rson,x-tree[lson].s-);
}
void dfsins(int k,int &x)
{
if (!k) return;
ins(x,tree[k].x);
dfsins(lson,x),dfsins(rson,x);
}
int merge(int x,int y)
{
if (tree[x].s<tree[y].s) swap(x,y);
dfsins(y,x);
return x;
}
void dfs(int k)
{
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=fa[k])
{
dfs(edge[i].to);
root[k]=merge(root[k],root[edge[i].to]);
}
int x=qrank(root[k],a[k]);
if (x<tree[root[k]].s) del(root[k],find(root[k],x+));
ins(root[k],a[k]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj4919.in","r",stdin);
freopen("bzoj4919.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();srand();
for (int i=;i<=n;i++)
{
b[i]=a[i]=read(),fa[i]=read();
addedge(fa[i],i);
}
sort(b+,b+n+);
int u=unique(b+,b+n+)-b-;
for (int i=;i<=n;i++) a[i]=lower_bound(b+,b+u+,a[i])-b;
dfs();
cout<<tree[root[]].s;
return ;
}

BZOJ4919 大根堆(动态规划+treap+启发式合并)的更多相关文章

  1. BZOJ4919 [Lydsy1706月赛]大根堆 【dp + 启发式合并】

    题目链接 BZOJ4919 题解 链上的\(LIS\)维护一个数组\(f[i]\)表示长度为\(i\)的\(LIS\)最小的结尾大小 我们可以用\(multiset\)来维护这个数组,子树互不影响,启 ...

  2. 2021-06-14 BZOJ4919:大根堆

    BZOJ4919:大根堆 Description: 题目描述   给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你 ...

  3. BZOJ 2733: [HNOI2012]永无乡(treap + 启发式合并 + 并查集)

    不难...treap + 启发式合并 + 并查集 搞搞就行了 --------------------------------------------------------------------- ...

  4. 【bzoj2733】[HNOI2012]永无乡 Treap启发式合并

    题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...

  5. bzoj4919 大根堆

    考虑二分求序列LIS的过程. g[i]表示长度为i的LIS最小以多少结尾. 对于每个数,二分寻找插入的位置来更新g数组. 放到树上也是一样,额外加上一个合并儿子的过程. 发现儿子与儿子直接是互不影响的 ...

  6. 【20181026T2】**图【最小瓶颈路+非旋Treap+启发式合并】

    题面 [错解] 最大最小?最小生成树嘛 蛤?还要求和? 点分治? 不可做啊 写了个MST+暴力LCA,30pts,140多行 事后发现30分是给dijkstra的 woc [正解] 树上计数问题:①并 ...

  7. 【bzoj2733】永无乡(无旋treap启发式合并 + 并查集)

    传送门 题目分析 起初每个岛都是一个平衡树, 并查集的祖先都是自己.合并两岛时,pri较小的祖先会被作为合并后的祖先, 而两颗平衡树采用启发式合并.查询k值就是基本操作. code #include& ...

  8. treap启发式合并

    注意输入v要在建根的前面. #include <cstdio> #include <iostream> #include <algorithm> #include ...

  9. BZOJ4919:[Lydsy1706月赛]大根堆(set启发式合并)

    Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质: ...

随机推荐

  1. day 12 列表字典 补充

    1.列表list的遍历 ##### while遍历 需要len(list) list = [11,22,33,44,55] len_list = len(list) i = 0 while i< ...

  2. sqlserver2008 数据库

    删除数据库提示: 无法对 数据库'DBName' 执行 删除,因为它正用于复制 之前建立过此数据库的发布订阅,但是后来删掉了发布订阅,也将对应的作业停止了,仍然报这个错,遂用此命令强制删除发布: sp ...

  3. HBase第三章 过滤器

    1  列值过滤器 SingleColumnValueFilter 对列值进行过滤. @Test public void scanDataByFilter() throws IOException { ...

  4. Redis5.0:在这些场景使用,高效率还低成本!

    很多大型电商网站.视频直播和游戏应用等,存在大规模数据访问,对数据查询效率要求高,且数据结构简单,不涉及太多关联查询. 这种场景使用Redis,在速度上对传统磁盘数据库有很大优势,能够有效减少数据库磁 ...

  5. Hackerank-Array-NewYearChaos

    题目背景描述 新年第一天,N 个人排队坐过山车.每个人穿有带编号的衣服 \([1, 2, 3, ...]\). 因为排队时间太久,有人发现给前面相邻的人喂一颗糖,就可以和他交换位置,而每人手里只有两颗 ...

  6. 53. [LeetCode] Maximum Subarray

    Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...

  7. Paper Reading - Im2Text: Describing Images Using 1 Million Captioned Photographs ( NIPS 2011 )

    Link of the Paper: http://papers.nips.cc/paper/4470-im2text-describing-images-using-1-million-captio ...

  8. zabbix监控历史数据清理

    2018/12/24 14:00:57  zabbix监控运行一段时间以后,会留下大量的历史监控数据,zabbix数据库一直在增大:可能会造成系统性能下降,查看历史数据室查询速度缓慢. zabbix里 ...

  9. Amazon - removed your selling privileges and placed a temporary hold on any funds - 1

    Hello, We are writing to let you know that we have removed your selling privileges and placed a temp ...

  10. Yii2 UploadedFile上传文件

    通过 UploadFile::getInstance($model, $attribute); UploadFile::getInstances($model, $attribute); Upload ...