LOJ.6282.数列分块入门6(块状链表/分块)
题目链接
1.分块(vector)+重构
//直接上vector(本机还是比较慢的...) 某块size较大时O(n)重构
//注意细节
#include <cmath>
#include <cstdio>
#include <cctype>
#include <vector>
#define gc() getchar()
#define pb push_back
typedef long long LL;
const int N=1e5+5;
int n,size,tmp[N<<1],bel;
std::vector<int> v[500];
std::vector<int>::iterator it;
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline int Get_Pos(int &p)
{
for(int i=1; i<=bel; ++i)
if((p-=v[i].size())<=0) {p+=v[i].size(); return i;}
}
void Rebuild()
{
int tot=0;
for(int i=1; i<=bel; ++i)
{
for(it=v[i].begin(); it!=v[i].end(); ++it) tmp[++tot]=*it;
v[i].clear();
}
size=sqrt(tot);
for(int i=1; i<=tot; ++i) bel=(i-1)/size+1, v[bel].pb(tmp[i]);
}
void Insert(int p,int val)
{
int id=Get_Pos(p);
v[id].insert(v[id].begin()+p-1,val);
if(v[id].size()>size*15) Rebuild();
}
int main()
{
n=read(), size=sqrt(n);
for(int i=1; i<=n; ++i) bel=(i-1)/size+1,v[bel].pb(read());
for(int opt,l,r,c,id,i=1; i<=n; ++i)
{
opt=read(),l=read(),r=read(),c=read();
if(opt) id=Get_Pos(r),printf("%d\n",v[id][r-1]);
else Insert(l,r);
}
return 0;
}
2.块状链表
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=1e5+5;
int n,size,H[N],nxt[N],nxtv[N<<1],A[N<<1],sz[N];//二倍数组!mdzzC++数组越界各种奇葩错误(这指针无语)
inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
inline int New_Node()
{
static int cnt=n;
return ++cnt;
}
inline int New_Block()
{
static int cnt=(n-1)/size+1;
return ++cnt;
}
void Init()
{
for(int i=1; i<=n; ++i) A[i]=read();
int tot=(n-1)/size+1;
H[0]=1;
for(int now=0,i=1; i<tot; ++i)//块整体的链表
H[i]=(i-1)*size+1, nxt[i]=i+1, sz[i]=size;
sz[tot]=n-(tot-1)*size, H[tot]=(tot-1)*size+1;
for(int i=1,tmp=i*size; i<=tot; tmp=++i*size)//块内链表
for(int j=(i-1)*size+1; j<tmp; ++j)
nxtv[j]=j+1;
}
int Get_Pos(int &p)
{
for(int i=H[0]; i; i=nxt[i])
if((p-=sz[i])<=0) {p+=sz[i]; return i;}
}
int Query(int p)
{
int id=Get_Pos(p);
for(int i=H[id]; i; i=nxtv[i])
if(!--p) return A[i];
}
void Insert(int p,int v)
{
int id=Get_Pos(p),pos=New_Node();
A[pos]=v, ++sz[id];
// printf("I pos:%d id:%d p:%d size:%d stdsz:%d sz[id]:%d\n",pos,id,p,size*(id-1)+p,size,sz[id]);
if(!p) nxtv[pos]=H[id], H[id]=pos;
else
for(int i=H[id]; i; i=nxtv[i])
if(!--p) {nxtv[pos]=nxtv[i], nxtv[i]=pos; break;}
if(sz[id] > size<<1)//2倍比较合适
{
p=size;
for(int i=H[id]; i; i=nxtv[i])
if(!(--p)) {pos=nxtv[i], nxtv[i]=0; break;}
int posb=New_Block();
H[posb]=pos, nxt[posb]=nxt[id], nxt[id]=posb, sz[posb]=sz[id]-size, sz[id]=size;
}
}
//void Print()
//{
// puts("Output:");
// for(int i=H[0]; i; i=nxt[i])
// for(int j=H[i]; j; j=nxtv[j])
// printf("%d ",A[j]);
// putchar('\n');
//}
int main()
{
n=read(), size=sqrt(n);
Init();
for(int opt,l,r,c,i=1; i<=n; ++i)
{
opt=read(),l=read(),r=read(),c=read();
if(opt) printf("%d\n",Query(r));
else Insert(l-1,r);
}
return 0;
}
LOJ.6282.数列分块入门6(块状链表/分块)的更多相关文章
- LOJ #6282. 数列分块入门 6-分块(单点插入、单点查询、数据随机生成)
#6282. 数列分块入门 6 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 1 题目描述 给出 ...
- 【函数式权值分块】【块状链表】bzoj3065 带插入区间K小值
显然是块状链表的经典题.但是经典做法的复杂度是O(n*sqrt(n)*log^2(n))的,出题人明确说了会卡掉. 于是我们考虑每个块内记录前n个块的权值分块. 查询的时候差分什么的,复杂度就是O(n ...
- LOJ#6282. 数列分块入门 6
一个动态的插入过程,还需要带有查询操作. 我可以把区间先分块,然后每个块块用vector来维护它的插入和查询操作,但是如果我现在这个块里的vector太大了,我可能的操作会变的太大,所以这时候我需要把 ...
- 题解【loj6277】数列分块入门1
题目描述 给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,单点查值. 输入格式 第一行输入一个数字\(n\). 第二行输入\(n\)个数字,第\(i\)个数字为\(a_{i}\) ...
- ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)
题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...
- 块状链表 bzoj 3343教主的魔法
//块状链表//分块排序,然后每次查找时在暴力查找头和尾两个块.//中间那些块,因为有序所以只需2分查找即可.我用的是lower_pound();//插入是,也是头和尾暴力插入,中间那些加到一个累计里 ...
- [Loj] 数列分块入门 1 - 9
数列分块入门 1 https://loj.ac/problem/6277 区间加 + 单点查询 #include <iostream> #include <cstdio> #i ...
- LOJ——#6277. 数列分块入门 1
~~推荐播客~~ 「分块」数列分块入门1 – 9 by hzwer 浅谈基础根号算法——分块 博主蒟蒻,有缘人可直接观摩以上大佬的博客... #6277. 数列分块入门 1 题目大意: 给出一个长为 ...
- 数列分块入门九题(二):LOJ6280~6282
Preface 个人感觉这中间的三题是最水的没有之一 数列分块入门 4--区间加法,区间求和 这个也是很多数据结构完爆的题目线段树入门题,但是练分块我们就要写吗 修改还是与之前类似,只不过我们要维护每 ...
随机推荐
- classfication中使用图像金字塔和sliding windows提高准确率
之前对imagenet的预训模型进行finetune,找出了很多样本选择时的注意事项,当时在测试如下这张照片时,效果不好,我认为是物体过小造成的,因此尝试使用图像金字塔的方法: 当时结果如下: 一开始 ...
- linux 高级字符设备驱动 ioctl操作介绍 例程分析实现【转】
转自:http://my.oschina.net/u/274829/blog/285014 1,ioctl介绍 ioctl控制设备读写数据以及关闭等. 用户空间函数原型:int ioctl(int f ...
- 福利爬虫妹子图之获取种子url
import os import uuid from lxml import html import aiofiles import logging from ruia import Spider, ...
- centos6.7环境之kvm虚拟化quem工具配置及使用详解
环境准备 需要勾选CPU的虚拟化支持,支持cpu虚拟化的CPU列表: intel支持虚拟化技术CPU列表: Intel 6 Cores / 12 Threads CPU Number: Code Na ...
- 基于url拦截
- python在windows下安装
打开python官方网站:https://www.python.org/downloads/ 点击下载 翻到底下的file目录下 选择对应的32,64位系统进行安装 一般来说选择Windows x86 ...
- python 全栈开发,Day125(HTML5+ 初识,HBuilder,夜神模拟器,Webview)
昨日内容回顾 1.增删改查: 增: db.collections.insert({a:1}) // 官方不推荐了 db.collections.insertMany([{a:1},{b:1}]) in ...
- Centos7.1 mini版安装后安装图形界面教程
[1]GNOME安装 1.执行下面命令安装GNOME Desktop Environment yum -y groups install "GNOME Desktop" 2.安装完 ...
- Ext.js入门(二)
ExtJs OOP基础 一:ExtJs中的面向对象 1.ExtJs中命名空间的定义 Ext中的命名空间类似于C#中的namespace和java中的包,用来对工程中的类进行更好的 ...
- hdu 1025 上面n个点与下面n个点对应连线 求最多能连有多少条不相交的线 (LIS)
题目大意有2n个城市,其中有n个富有的城市,n个贫穷的城市,其中富有的城市只在一种资源富有,且富有的城市之间富有的资源都不相同,贫穷的城市只有一种资源贫穷,且各不相同,现在给出一部分贫穷城市的需求,每 ...