昨天看了可并堆是什么,写的是左偏树

大概就是一棵树

1、有左偏性质,即当前根到左叶子节点距离比到右叶子节点距离大

2、有堆性质,堆顶关键字比子树关键字小

合并两个堆的时候,关键字大的插入到关键字小的那堆的右子树中,右子树的深度大于左子树时交换两者以维持左偏性质。

堆中个数太多的时候,pop堆顶的元素x

具体是合并左右两个子树后返回新的堆顶元素y,清除完x的信息后root[x]指向y

bzoj1455:用并查集合并团,用可并堆维护团中最小的人。

 #include<stdio.h>
 #include<string.h>
 #include<algorithm>
 using namespace std;
 ;
 int n,m,v[maxn],vis[maxn],fa[maxn],l[maxn],r[maxn],a,b,d[maxn];
 ];

 int find(int x){
     return (fa[x]==x)?x:fa[x]=find(fa[x]);
 }

 int merge(int x, int y){
     if (!x || !y) return x+y;
     if (v[x]>v[y]) swap(x,y);  //保证堆顶最小
     r[x]=merge(r[x],y);
     if (d[r[x]]>d[l[x]]) swap(l[x],r[x]);
     d[x]=d[r[x]]+;
     return x;
 }

 int main(){
     scanf("%d", &n);
     ; i<=n; i++) scanf("%d", &v[i]);
     scanf(]=-;
     ; i<=n; i++) fa[i]=i;
     ; i<=m; i++){
         scanf("%s", s);
         ]=='M'){
             scanf("%d%d", &a, &b);
             if (vis[a] || vis[b]) continue;
             int fx=find(a), fy=find(b);
             if (fx!=fy) fa[fx]=fa[fy]=merge(fx,fy); // 合并从堆顶开始合并
         }else{
             scanf("%d", &a);
             ");
             else{
                 ;// printf("  %d\n", fx);
                 printf("%d\n", v[fx]);
                 fa[fx]=merge(l[fx],r[fx]);
                 fa[fa[fx]]=fa[fx];
             }
         }
     }
     ;
 }

bzoj2809:DFS一遍,从叶子节点开始向上递归,到一个节点,可并堆维护当前子树中满足预算的最多人数,然后用当前子树更新答案。具体是每个节点都插入,超出预算就pop最大花费的人直到满足预算

 #include<stdio.h>
 #include<string.h>
 #include<algorithm>
 #define LL long long
 using namespace std;
 ;
 struct node{
     int to,next;
 }e[maxn];
 struct heap{
     int l,r;
     LL val;
 }t[maxn];
 ,head[maxn];
 LL v[maxn],w[maxn],ans,sum[maxn],add[maxn];

 void insert(int u, int v){
     e[++tot].to=v; e[tot].next=head[u]; head[u]=tot;
 }

 int merge(int x, int y){
     if (!x || !y) return x+y;
     if (t[x].val<t[y].val) swap(x,y);
     t[x].l=merge(t[x].l,y);
     swap(t[x].l,t[x].r);
     return x;
 }

 void Pop(int x){
     int rt=root[x];
     root[x]=merge(t[rt].l,t[rt].r);
     sum[x]--; add[x]-=t[rt].val;
     t[rt].l=t[rt].r=t[rt].val=;
 }

 void dfs(int u){
     add[u]=sum[u]=;
     for (int i=head[u],vv; i; i=e[i].next){
         dfs(vv=e[i].to);
         add[u]+=add[vv]; sum[u]+=sum[vv];
         root[u]=merge(root[u],root[vv]);
         while (add[u]>m) Pop(u);
     }
     add[u]+=v[u]; sum[u]++;
     t[u]=(heap){,,v[u]};
     root[u]=merge(root[u],u);
     while (add[u]>m) Pop(u);
     ans=max(ans,sum[u]*w[u]);
 }

 int main(){
     scanf("%d%d", &n, &m); int s;
     ; i<=n; i++){
         int x;
         scanf("%d%lld%lld", &x, &v[i], &w[i]);
         insert(x,i); if (!x) s=i;
     }
     dfs(s);
     printf("%lld\n", ans);
     ;
 }

bzoj1455: 罗马游戏 + bzoj2809: Dispatching(可并堆)的更多相关文章

  1. [bzoj1455]罗马游戏_左偏树_并查集

    罗马游戏 bzoj-1455 题目大意:给你n个人,2种操作,m次操作:1.将i号士兵所在的集合的最小值删除 2.合并i和j两个士兵所在的团体 注释:$1\le n\le 10^6$,$1\le m ...

  2. [BZOJ1455]罗马游戏 左偏树+并查集

    1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 2285  Solved: 994[Submit][Status][Discuss] ...

  3. BZOJ1455 罗马游戏 左偏树 可并堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1455 题意概括 n个人,2种操作. 一种是合并两个人团,一种是杀死某一个人团的最弱的人. 题解 左 ...

  4. Bzoj1455 罗马游戏

    Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1622  Solved: 679 Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人 ...

  5. 【数据结构】bzoj1455罗马游戏

    Description 罗马皇帝很喜欢玩杀人游戏. 他的军队里面有n个人,每个人都是一个独立的团.最近举行了一次平面几何测试,每个人都得到了一个分数. 皇帝很喜欢平面几何,他对那些得分很低的人嗤之以鼻 ...

  6. BZOJ1455——罗马游戏

    1.题目大意:维护一个数据结构,可以实现合并操作,还能询问最小值 2.分析:这种问题当然是可并堆啦 随便写了一个左偏树QAQ #include <cstdio> #include < ...

  7. [BZOJ1455]罗马游戏(左偏树)

    用并查集和左偏树维护士兵的关系 Code #include <cstdio> #include <algorithm> #define N 1000010 using name ...

  8. BZOJ1455罗马游戏

    左偏树裸题. 题面描述让人意识到了平面几何的重要性. //Achen #include<algorithm> #include<iostream> #include<cs ...

  9. 【BZOJ-1455】罗马游戏 可并堆 (左偏树)

    1455: 罗马游戏 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1355  Solved: 561[Submit][Status][Discuss] ...

随机推荐

  1. Linux学习记录

    ---恢复内容开始--- linux与unix的关系 linux是借鉴了unix设计思想,也称linux位类unix系统. Linux常用命令 1.命令基本格式 命令[选项][参数] 注意:个别命令不 ...

  2. 高德地图纯js和html

    <!doctype html> <html> <head> <meta content="" charset="utf-8&qu ...

  3. Adobe illustrator & Photoshop 处理图片

    Adobe illustrator 置入,可以将多张图片放在一张纸 (一个sheet)里面. Adobe photoshop: 新建一个图层,然后置入,将图片导入,然后裁剪,最后另存为就可以得到最后的 ...

  4. ajax+php+mysql 实现点赞、局部刷新,每个IP只能对一篇文章点赞一次

    主要流程: 点赞—>判断当前设备IP是否对当前文章有过点赞记录—>若有记录,弹出提示“已经赞过了”; 若无记录,当前文章点赞数+1,并在记录设备IP点赞记录的表中插入信息. 文章表 art ...

  5. java.sql.SQLException: ORA-01000: 超出打开游标的最大数

    实际上,这个错误的原因,主要还是代码问题引起的.  ora-01000: maximum open cursors exceeded.  表示已经达到一个进程打开的最大游标数.  这样的错误很容易出现 ...

  6. gulp如何使用

    简介: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成:使用她,我们不仅可以很愉快的编写代码 ...

  7. tp框架之文件上传

    控制器 function wenjian() { if(empty($_FILES)) { $this->display(); } else { $u = new \Think\Upload() ...

  8. JSP网页处理过程

    以下步骤表明了Web服务器是如何使用JSP来创建网页的:  就像其他普通的网页一样,您的浏览器发送一个HTTP请求给服务器. Web服务器识别出这是一个对JSP网页的请求,并且将该请求传递给JSP引擎 ...

  9. CSS中定义CLASS时,中间有空格和没空格的区别是什么?

    .example .pp{ color: orange; } .example.pp2 { color: green; }如上面的两个定义一个是中间有空格,一个是中间没空格. 第一个class要这样写 ...

  10. Python 爬取网站资源文件

    爬虫原理: 以下来自知乎解释 首先你要明白爬虫怎样工作.想象你是一只蜘蛛,现在你被放到了互联“网”上.那么,你需要把所有的网页都看一遍.怎么办呢?没问题呀,你就随便从某个地方开始,比如说人民日报的首页 ...