【OI】指针线段树&指针
对于线段树,我们一般需要n*4的空间去存储线段树,然后有一种玄学操作是用指针来实现线段树。
#include <inttypes.h>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#define debug(x) std::cout<< #x << " = " << std::endl; typedef long long int int_t; using std::cin;
using std::cout;
using std::endl; struct Node{ Node *left,*right;
int_t value;
int begin,end;
int mark;
Node(int begin, int end) {
this->begin = begin;
this->end = end;
left = right = NULL;
mark = ;
} void add(int_t val) {
this->value += (end - begin + ) * val;
mark += val;
} void maintain() {
if(begin != end) {
this->value = left -> value + right->value; } } void pushDown(){
if (mark) { if(begin!= end) {
left -> add(mark);
right -> add(mark); }
mark = ;
}
} int_t query (int begin,int end){
if(end < this->begin || begin > this->end) return ;
if(this->begin >= begin && this->end <= end) return this->value;
this->pushDown();
return left->query(begin,end) + right->query(begin, end) ; } void add(int begin,int end,int_t val){
if(end < this->begin || begin > this->end) return;
if(this->begin >= begin && this->end <= end) {
this->add(val);
return ;
}
this->pushDown();
left->add(begin,end,val);
right->add(begin,end,val);
this->maintain();
} };
char buf[*sizeof(Node)];
int used = ; void* allocate() { return (++used) * sizeof(Node) + buf;} const int MaxN = ;
Node* tree;
int_t a[MaxN];
int n,m; Node* build(int begin,int end){
int mid = (begin + end)/; Node* node = new(allocate()) Node(begin,end);
if(begin != end){
node->left = build(begin ,mid);
node->right = build(mid+,end); } else if(begin == end){
node->value = a[begin];
} node->maintain();
return node;
} int main(){
scanf("%d%d",&n,&m); for(int i = ; i <= n; i++){
scanf("%lld",&a[i]);
} tree = build(,n); for(int i = ; i <= m; i++){
int opt,x,y;
int_t k;
scanf("%d",&opt);
if(opt == ){
scanf("%d%d%lld",&x,&y,&k);
tree->add(x,y,k); }
else
{
scanf("%d%d",&x,&y); printf("%lld\n",tree->query(x,y));
}
} return ;
}
Code
接着这个代码说一下指针:
声明指针的方法是 type *x;
例如 int* a;
这样就是声明了一个int类型的指针,没有指向任何的内存。
然后,可以使用 int* a = NULL; 来初始化它,这时候它是一个空指针,一旦对它试图对它操作就会RE,比如 int* a = NULL;
指针本质上一个存贮8比特地址的整形变量,所以应该使用取地址符&来给指针赋值:
int c;
int *a = &c;
我们要通过指针给原本元素赋值:
int c = 0;
int *a = &c;
*a = 5;
这时输出c的值为5
另一种写法是引用,相当于给了某个变量另一个名字,本质仍然是存储地址。
int c = 0;
int &a = c;
a = 5;
与上面的写法是一样的效果。
指针不一定要指向某个变量,可以直接指向某个内存空间。
例如,我声明了一个结构体 struct custom{int a,b;};
然后,我们就可以使用指针指向内存中一个custom类型的内存,例如 custom* cs = new custom;
通过new关键字为这个指针创建一块内存,这个指针就指向它。
但是,如果想访问这个结构体的成员,则不同于原来的 "."访问,需要用 "->"来访问成员。
例如, cs->a = 0; 这样就算是给这个指针指向的结构体内存的a成员赋值为0。
但是,new是系统自动为其分配内存,比较慢,所以我们就可以创建一块内存池: char buf[400010*sizeof(custom)];
然后,用一个变量记录已经使用了内存池中的多少内存:int used = 0;
定义向这个内存池分配内存的函数:void* allocate() { return (++used) * sizeof(custom) + buf;}
used每次加1,记录已经使用了used个大小为sizeof(custom)的内存,然后加号后面是创建的内存池。
于是就可以使用这个内存池来分配内存:
custom *cs;
cs = new(allocate()) custom;
类型后面可以跟上构造函数,假设我们的custom有这样的构造函数:
custom(int a,int b){this->a = a;this->b = b;}
于是分配内存时就可以这样写:cs = new(allocate()) custom(1,2);
【OI】指针线段树&指针的更多相关文章
- BZOJ4695 最假女选手(势能线段树)
BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...
- BZOJ 4695 最假女选手 线段树
题意: 给定一个长度为 N序列,编号从1 到 N.要求支持下面几种操作: 1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于x ...
- P2801 教主的魔法 (线段树)
题目 P2801 教主的魔法 解析 成天做水题 线段树,第一问区间加很简单 第二问可以维护一个区间最大值和一个区间最小值,若C小于等于区间最小值,就加上区间长度,若C大于区间最大值,就加0 ps:求教 ...
- 指针-动态开点&合并线段树
一个知识点不在一道题里说是没有灵魂的 线段树是用来处理区间信息的咯 但是往往因为需要4倍空间让许多人退却,而动态开点的线段树就非常棒 仿佛只用2倍就可以咯 指针保存位置,即节点信息,是很舒适的,所以用 ...
- CF547E Milk and Friends(AC自动机的fail指针上建主席树 或 广义后缀自动机的parent线段树合并)
What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercas ...
- 主席树-指针实现-找第k小数
主席树,其实就是N颗线段树 只是他们公用了一部分节点(๑•̀ㅂ•́)و✧ 我大部分的代码是从一位大佬的那里看到的 我这个垃圾程序连Poj2104上的数据都过不了TLE so希望神犇能给我看看, 顺便给 ...
- 【线段树哈希】「Balkan OI 2016」Haker
1A海星 题目大意 给你一个长度为 $n$ ,由小写字母构成的字符串 $S$ 和 $Q$ 个操作,每个操作是以下 3 种之一: 1 x y k :询问当前字符串从位置 $x$ 到 $y$ 的子串与从位 ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
- 【线段树】bzoj1756 Vijos1083 小白逛公园
我们知道,求一段序列的最大子段和是O(n)的,但是这样是显然会超时的. 我们需要一个数据结构来支持修改和计算的操作,对于这种修改一个而查询区间的问题,考虑使用线段树. 在线段树中,除了左端点,右端点, ...
随机推荐
- C++如何显式调用常成员函数
C++的常成员函数与同名成员函数重载时,该如何显式调用常成员函数? 具体的一个小例子: #include <iostream> using namespace std; class C1 ...
- BZOJ 1565 植物大战僵尸 最大权闭合子图+网络流
题意: 植物大战僵尸,一个n*m的格子,每 个格子里有一个植物,每个植物有两个属性: (1)价值: (2)保护集合,也就是这个植物可以保护矩阵中的某些格子. 现在你是僵尸,你每次只能从(i,m) 格子 ...
- 用pandas展示数据输出时列名不能对齐
列名用了中文的缘故,设置pandas的参数即可,代码如下: import pandas as pd #这两个参数的默认设置都是False pd.set_option('display.unicode. ...
- [bzoj1078][SCOI2008][斜堆] (贪心)
Description 斜堆(skew heap)是一种常用的数据结构.它也是二叉树,且满足与二叉堆相同的堆性质:每个非根结点的值都比它父亲大.因此在整棵斜堆中,根的值最小.但斜堆不必是平衡的,每个结 ...
- linux中的命令
1,ln-链接 功能是为某一个文件在另外一个位置建立一个同步的链接,这个命令最常用的参数是-s,具体用法是: ln -s 源文件 目标文件 // -s 是 symbolic(符号,象征)的意思. l ...
- 嵌入式linux启动信息完全注释
嵌入式linux启动信息完全注释 from:http://www.embedlinux.cn/ShowPost.asp?ThreadID=377 摘要 我们在这里讨论的是对嵌入式linux系统的启动过 ...
- Oracle导出txt文本文件
转自: http://blog.csdn.net/ahngzw77/article/details/8652722 对于SPOOL数据的SQL,最好要自己定义格式,以方便程序直接导入,SQL语句如: ...
- UVA 10652 凸包问题
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> # ...
- Thinkphp5.0 的使用模型Model查询
Thinkphp5.0 的使用模型Model查询 一.查询多条记录 获取多个数据可以使用:select()方法和all()方法. 示例一:使用all()方法. //(1)筛选条件使用闭包函数 $res ...
- [bzoj4827][Hnoi2017]礼物_FFT
礼物 bzoj-4827 Hnoi-2017 题目大意:给定两个长度为$n$的手环,第一个手环上的$n$个权值为$x_i$,第二个为$y_i$.现在我可以同时将所有的$x_i$同时加上自然数$c$.我 ...