【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)的,但是这样是显然会超时的. 我们需要一个数据结构来支持修改和计算的操作,对于这种修改一个而查询区间的问题,考虑使用线段树. 在线段树中,除了左端点,右端点, ...
随机推荐
- 初次使用IDEA创建maven项目
第一次使用IDEA,创建一个maven项目,首先下载maven,官方地址:http://maven.apache.org/download.cgi 解压,在环境变量里配置 path里 D:\maven ...
- 虚拟机Linux与本地虚拟网卡配置---NAT链接方式
虚拟机Linux与本地虚拟网卡配置---NAT链接方式 **********这是我亲自尝试多次实践出来的结果,不是复制粘贴************************* 首先进行初始化,这样避免有 ...
- Python和Java的语法对比,语法简洁上python的确完美胜出
Python是一种广泛使用的解释型.高级编程.通用型编程语言,由吉多·范罗苏姆创造,第一版发布于1991年.可以视之为一种改良(加入一些其他编程语言的优点,如面向对象)的LISP.Python的设计哲 ...
- linux下mysql的安装与使用
一.mysql的安装 之前搭建linux下项目的发布,最后遗留的问题时数据库的迁移,如何从windows上迁移到linux上?这里首先进行mysql数据库的安装 1.下载mysql安装包 在这里下载的 ...
- Python中的列表(4)
1.遍历列表 如果想打印列表中的所有元素,则必须遍历列表. 可以使用for ... in ... 语句来遍历列表中的元素.遍历的意思 words = ['a','b','c','d'] for wor ...
- 86-Money Flow Index 资金流量指数指标.(2015.7.3)
Money Flow Index 资金流量指数指标 计算: 1.典型价格(TP)=当日最高价.最低价与收盘价的算术平均值 2.货币流量(MF)=典型价格(TP)×N日内成交金额 3.如果当日MF> ...
- jQuery实现上传进度条效果
效果:(点击上传按钮) See the Pen pjGNJr by moyu (@MoYu1991) on CodePen. html代码: <!DOCTYPE html> <h ...
- android源码编译时拷贝替换指定文件
由于要做版本定制,某些版本的资源文件等(例如style.xml)需要不同的配置,但是android的编译开关无法在xml里使用,于是想到了编译时根据不同的编译开关编译不同的文件,如下: 1.建立A.x ...
- AtCoder Grand Contest 020 D - Min Max Repetition
q<=1000个询问,每次问a,b,c,d:f(a,b)表示含a个A,b个B的字符串中,连续A或连续B最小的串中,字典序最小的一个串,输出这个串的c到d位.a,b<=5e8,d-c+1&l ...
- POJ——T 2728 Desert King
http://poj.org/problem?id=2728 Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 27191 ...