用堆操作不断加入点来找到每个点对应所包含的值的个数的理解

首先还是要清楚一下堆操作的代码,毕竟线段树打多了,打堆的时候总会往线段树方向靠近

首先是建堆:

D=1;
for(;D<maxn+2;D<<=1);

然后给堆赋予值就可以了

查找区间段的和:
int query(int s,int t)
{
    int i=D+s-1,j=D+t+1,ans=0;
    for(;i^j^1;i>>=1,j>>=1){
        if(~i&1) ans+=sum[i^1];
        if(j&1) ans+=sum[j^1];
    }
    return ans;
}

更新操作:

void update(int i)
{
    for(;i^1;i>>=1)
        sum[i>>1]=sum[i]+sum[i^1];
}

之前也做了一道star level的题写成了博客,这里继续来写一遍,就是问对于一个星星的位置,比其x小于等于和y小于等于的点有多少个

这里我们所采取的是先进行一维上的排序,然后排好序后用另一维度来建树

如星星的题目已经以y的大小先后排好序了,那我们就省事了

我们从第一个节点不断添加进去,来找比它x小的数有几个,每次添加一个x,都要tree[D+x]++,再进行更新操作,因为后面的点是绝对不会影响到前面的点的

所以是可以这样做的:

第二题:

SPOJ RATING

这道题目也是两个维度,不过如果出现一样的值的话,者之间是不算谁比谁大的,这是跟星星不一样的地方

所以我们排好序后,每次添加点进入的时候还需要判断是否与前一个点值完全相同,如果相同不访问,直接继承前面一个点的值就可以了,然后再做更新

同时星星的点是题目本身按顺序给出的,而这里是乱序的,我们需要事先排好序然后不断添入点

我采取的方法是,建立结构体,除2维的数据外,还需记录id号,不然没法记录每个位置比别人大的个数

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 #define N 300005
 6 int sum[N<<2],D,maxn;
 7 struct Edge{
 8     int x,y,id;
 9     bool operator<(const Edge &m)const
10     {
11         return x==m.x?y<m.y:x<m.x;
12     }
13 }e[N];
14 void update(int i)
15 {
16     for(;i^1;i>>=1)
17         sum[i>>1]=sum[i]+sum[i^1];
18 }
19 int query(int s,int t)
20 {
21     int i=D+s-1,j=D+t+1,ans=0;
22     for(;i^j^1;i>>=1,j>>=1){
23         if(~i&1) ans+=sum[i^1];
24         if(j&1) ans+=sum[j^1];
25     }
26     return ans;
27 }
28 int main()
29 {
30     int n,ans[N];
31     maxn=0;
32     memset(sum,0,sizeof(sum));
33     scanf("%d",&n);
34     for(int i=0;i<n;i++){
35         scanf("%d%d",&e[i].x,&e[i].y);
36         maxn=max(maxn,e[i].y);
37         e[i].id=i;
38     }
39     D=1;
40     for(;D<maxn+2;D<<=1);
41     sort(e,e+n);
42     int k;
43     for(int i=0;i<n;i++){
44         if(i>1&&e[i].x==e[i-1].x&&e[i].y==e[i-1].y){
45         }
46         else{
47             k=query(1,e[i].y);
48         }
49         ans[e[i].id]=k;
50         sum[D+e[i].y]++;
51         update(D+e[i].y);
52     }
53     for(int i=0;i<n;i++)
54         printf("%d\n",ans[i]);
55     return 0;
56 }

用堆操作不断加入点来找到每个点对应所包含的值的个数的理解

时间: 2024-07-30 21:48:59

用堆操作不断加入点来找到每个点对应所包含的值的个数的理解的相关文章

C++ STL堆操作

/* STL 最大堆.最小堆的应用 */ #include <iostream> #include <vector> #include <algorithm> // using namespace std; /* STL 堆操作 (1)make_heap()构造堆 void make_heap(first_pointer,end_pointer,compare_function); 默认比较函数是(<),即最大堆. 函数的作用是将[begin,end)内的元素处理

不用比较找到数组中两个不同的值

/**     *    找到数组中两个不同的值     *     /     public static void main(String[] args) { int[] arr={2,2,1,1,3,4}; int eo = eh(arr); int offset = getOffset(eo); int eo1 = 0; for(int i:arr){ if(((i>>offset)&1)==1)continue; eo1 ^= i; } System.out.println(

STL之堆操作

首先来看完全二叉树的定义: 若设二叉树的深度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树.而将一维数组视为完全二叉树书得到的即为堆. 堆效率极高,像十分常用的排序算法.Dijkstra算法.Prim算法等都要用堆才能优化,几乎每次都要考到的二叉排序树的效率也要借助平衡性来提高,而平衡性基于完全二叉树. STL中与堆相关的4个函数--建立堆make_heap(),在堆中添加数据push_heap(),在堆中删除数据

SQL Server 触发器例题: --次性删除course表数据,使用触发器替换删除操作,先删除外键表相关数据,再删除course。很难理解

create trigger Course_Delete on course instead of delete as declare @cno varchar(20) --定义变量 select @cno = cno from deleted --临时表里的信息是instead of 替换 delete要删除的信息 delete from score where cno = @cno --instead of 替换操作后执行的代码命令 delete from course where cno=

js数组操作 求最大值,最小值,正序、倒叙大小值排序,去重复

var arr = [1,5,2,56,12,34,21,3,5] Math.min.apply({},arr) // 1 Math.max.apply({},arr) // 56 arr.sort((m,n)=>m-n) // [1, 2, 3, 5, 5, 12, 21, 34, 56] arr.sort((m,n)=>n-m) //[56, 34, 21, 12, 5, 5, 3, 2, 1] 去重复 var arr = [2,1,4,3,2,4,2,3,4,2,6,5,5] var o

C# 类型基础 值类型和引用类型

引言 本文之初的目的是讲述设计模式中的 Prototype(原型)模式,但是如果想较清楚地弄明白这个模式,需要了解对象克隆(Object Clone),Clone其实也就是对象复制.复制又分为了浅度复制(Shallow Copy)和深度复制(Deep Copy),浅度复制和深度复制又是以如何复制引用类型成员来划分的.由此又引出了引用类型和值类型,以及相关的对象判等.装箱.拆箱等基础知识.索性从最基础的类型开始自底向上写起. 值类型和引用类型 先简单回顾一下C#中的类型系统.C# 中的类型一共分为

用CIL写程序:写个函数做加法

前言: 上一篇文章小匹夫为CIL正名的篇幅比较多,反而忽略了写那篇文章初衷--即通过写CIL代码来熟悉它,了解它.那么既然有上一篇文章做基础(炮灰),想必各位对CIL的存在也就释然了,兴许也燃起了一点探索它,掌握它的欲望.那么小匹夫就继续扯一扯CIL,接下来的几篇文章也都以上一篇文章中的那个CIL实现的Hello Wolrd程序为基础,继续通过写CIL代码实现一些功能的方式来和各位探讨交流,同时也加深自己对CIL的掌握和印象. 人生就是做加法 "我的肩上搭着她得衣裳,我嗅着她留在衣服上的体香..

可以不做,但是不能不懂!

底子太薄,看东西太过于马虎,到现在感觉自己不会的东西太多,也没有相对来说精通的东西. 老话说的很对,以往那些觉得以后用不上可以跳过的东西在关键时候都会跳出来给你当头一棒!固然,即使社会如此之动荡,人心如此之浮躁.踏踏实实学点东西,弄明白点东西,这才是根本. 1. C语言数据类型 1 #define SECOND_YEAR_TIME 365*24*60*60*30UL 2 #include"stdio.h" 3 #include"math.h" 4 int main(

C# 类型基础(中)

前一篇文章中我们讲到了值类型和引用类型的一些区别,那这篇我们将深入的分析一下到底有什么不一样 先总结一下两者的差别: 黄金法则: 1.引用类型总是被分配到托管堆上. 2.值类型总是分配到它声明的地方: a.作为引用类型的成员变量分配到托管堆上 b.作为方法的局部变量时分配到栈上 这就是栈和托管堆的区别,栈是线程级别的存储,很规整的存储结构,有先进后出的规则.在每一个线程开启的时候系统默认会给线程分配大约1M左右的栈内存.而托管堆的存储是很随意的,我们对引用类型的操作都是在托管堆上的. 那么线程栈