hzwer分块九题(暂时持续更新)
hzwer分块9题
分块1:区间加法,单点查询
Code
#include<bits/stdc++.h>
#define in(i) (i=read())
using namespace std;
const int N=5e5+10,inf=2e9;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
return ans*f;
}
int n,m,block;
int pos[N],v[N],tag[N];
void add(int a,int b,int c) {
for(int i=a;i<=min(pos[a]*block,b);i++) v[i]+=c;
if(pos[a]!=pos[b])
for(int i=(pos[b]-1)*block+1;i<=b;i++) v[i]+=c;
for(int i=pos[a]+1;i<=pos[b]-1;i++) tag[i]+=c;
}
int main()
{
in(n); block=sqrt(n);
for(int i=1;i<=n;i++) in(v[i]);
for(int i=1;i<=n;i++)
pos[i]=(i-1)/block+1;
for(int i=1;i<=n;i++) {
int op,a,b,c;
in(op),in(a),in(b),in(c);
if(!op) add(a,b,c);
else cout<<v[b]+tag[pos[b]]<<endl;//a,c没用
}
}
分块2:区间加法,求区间内小于x的个数
提示:暴力+二分,但是由于一些数加了之后会改变顺序,所以要重构
Code
#include<bits/stdc++.h>
#define in(i) (i=read())
using namespace std;
const int N=5e5+10,inf=2e9;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
return ans*f;
}
int n,m,block;
int pos[N],v[N],tag[N];
vector<int>t[N];
void rebuild(int x) {
t[x].clear();
for(int i=(x-1)*block+1;i<=min(n,x*block);i++)
t[x].push_back(v[i]);
sort(t[x].begin(),t[x].end());
}
void add(int a,int b,int c) {
for(int i=a;i<=min(pos[a]*block,b);i++) v[i]+=c;
rebuild(pos[a]);
if(pos[a]!=pos[b]) {
for(int i=(pos[b]-1)*block+1;i<=b;i++) v[i]+=c;
rebuild(pos[b]);
}
for(int i=pos[a]+1;i<=pos[b]-1;i++) tag[i]+=c;
}
int query(int a,int b,int c,int ans=0) {
for(int i=a;i<=min(pos[a]*block,b);i++)
if(v[i]+tag[pos[a]]<c) ans++;
if(pos[a]!=pos[b])
for(int i=(pos[b]-1)*block+1;i<=b;i++)
if(v[i]+tag[pos[b]]<c) ans++;
for(int i=pos[a]+1;i<=pos[b]-1;i++) {
int x=c-tag[i];
ans+=lower_bound(t[i].begin(),t[i].end(),x)-t[i].begin();
}return ans;
}
int main()
{
in(n); block=sqrt(n);
for(int i=1;i<=n;i++) in(v[i]);
for(int i=1;i<=n;i++) {
pos[i]=(i-1)/block+1;
t[pos[i]].push_back(v[i]);
}
for(int i=1;i<=pos[n];i++) sort(t[i].begin(),t[i].end());
for(int i=1;i<=n;i++) {
int op,a,b,c;
in(op),in(a),in(b),in(c);
if(!op) add(a,b,c);
else cout<<query(a,b,c*c)<<endl;
}
}
分块3:区间加法,求前驱
提示:暴力+二分(set)
Code
#include<bits/stdc++.h>
#define in(i) (i=read())
using namespace std;
const int N=5e5+10,inf=2e9;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
return ans*f;
}
int n,m,block;
int pos[N],v[N],tag[N];
set<int>s[N];
void add(int a,int b,int c) {
for(int i=a;i<=min(pos[a]*block,b);i++) {
s[pos[a]].erase(v[i]);
s[pos[a]].insert(v[i]+=c);
}
if(pos[a]!=pos[b]) {
for(int i=(pos[b]-1)*block+1;i<=b;i++) {
s[pos[b]].erase(v[i]);
s[pos[b]].insert(v[i]+=c);
}
}
for(int i=pos[a]+1;i<=pos[b]-1;i++) tag[i]+=c;
}
int query(int a,int b,int c,int ans=-1) {
for(int i=a;i<=min(pos[a]*block,b);i++)
if(v[i]+tag[pos[a]]<c) ans=max(ans,v[i]+tag[pos[a]]);
if(pos[a]!=pos[b])
for(int i=(pos[b]-1)*block+1;i<=b;i++)
if(v[i]+tag[pos[b]]<c) ans=max(ans,v[i]+tag[pos[b]]);
for(int i=pos[a]+1;i<=pos[b]-1;i++) {
int x=c-tag[i];
set<int>::iterator it =s[i].lower_bound(x);
if(it==s[i].begin()) continue; it--;
ans=max(ans,*it+tag[i]);
}return ans;
}
int main()
{
in(n); block=sqrt(n);
for(int i=1;i<=n;i++) in(v[i]);
for(int i=1;i<=n;i++) {
pos[i]=(i-1)/block+1;
s[pos[i]].insert(v[i]);
}
for(int i=1;i<=n;i++) {
int op,a,b,c;
in(op),in(a),in(b),in(c);
if(!op) add(a,b,c);
else cout<<query(a,b,c)<<endl;
}
}
分块4:区间加法,区间求和
Code
#include<bits/stdc++.h>
#define in(i) (i=read())
using namespace std;
const int N=5e5+10,inf=2e9;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
return ans*f;
}
int n,m,block;
int pos[N],v[N],tag[N],sum[N];
void add(int a,int b,int c) {
for(int i=a;i<=min(pos[a]*block,b);i++) v[i]+=c,sum[pos[a]]+=c;
if(pos[a]!=pos[b])
for(int i=(pos[b]-1)*block+1;i<=b;i++) v[i]+=c,sum[pos[b]]+=c;
for(int i=pos[a]+1;i<=pos[b]-1;i++) tag[i]+=c;
}
int query(int a,int b,int ans=0) {
for(int i=a;i<=min(pos[a]*block,b);i++)
ans+=v[i]+tag[pos[a]];
if(pos[a]!=pos[b])
for(int i=(pos[b]-1)*block+1;i<=b;i++)
ans+=v[i]+tag[pos[b]];
for(int i=pos[a]+1;i<=pos[b]-1;i++)
ans+=sum[i]+block*tag[i];
return ans;
}
int main()
{
in(n); block=sqrt(n);
for(int i=1;i<=n;i++) in(v[i]);
for(int i=1;i<=n;i++)
pos[i]=(i-1)/block+1,sum[pos[i]]+=v[i];
for(int i=1;i<=n;i++) {
int op,a,b,c;
in(op),in(a),in(b),in(c);
if(!op) add(a,b,c);
else printf("%d\n",query(a,b)%(c+1));
}
}
分块5:区间开方,区间求和
提示:因为开方一些次数后,数会变成0/1,我们对不全为0/1的块暴力开方,否则跳过
Code
#include<bits/stdc++.h>
#define in(i) (i=read())
using namespace std;
const int N=5e5+10,inf=2e9;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
return ans*f;
}
int n,m,block;
int pos[N],v[N],tag[N],sum[N],vis[N];
void solve(int x) {
if(vis[x]) return;
vis[x]=1; sum[x]=0;
for(int i=(x-1)*block+1;i<=x*block;i++) {
v[i]=sqrt(v[i]); sum[x]+=v[i];
if(v[i]>1) vis[x]=0;
}
}
void update(int a,int b,int c) {
for(int i=a;i<=min(b,pos[a]*block);i++) {
sum[pos[a]]-=v[i];
v[i]=sqrt(v[i]);
sum[pos[a]]+=v[i];
}
if(pos[a]!=pos[b])
for(int i=(pos[b]-1)*block+1;i<=b;i++) {
sum[pos[b]]-=v[i];
v[i]=sqrt(v[i]);
sum[pos[b]]+=v[i];
}
for(int i=pos[a]+1;i<=pos[b]-1;i++) solve(i);
}
int query(int a,int b,int ans=0) {
for(int i=a;i<=min(pos[a]*block,b);i++)
ans+=v[i]+tag[pos[a]];
if(pos[a]!=pos[b])
for(int i=(pos[b]-1)*block+1;i<=b;i++)
ans+=v[i]+tag[pos[b]];
for(int i=pos[a]+1;i<=pos[b]-1;i++)
ans+=sum[i]+block*tag[i];
return ans;
}
int main()
{
in(n); block=sqrt(n);
for(int i=1;i<=n;i++) in(v[i]);
for(int i=1;i<=n;i++)
pos[i]=(i-1)/block+1,sum[pos[i]]+=v[i];
for(int i=1;i<=n;i++) {
int op,a,b,c;
in(op),in(a),in(b),in(c);
if(!op) update(a,b,c);
else printf("%d\n",query(a,b)%(c+1));
}
}
分块6:插入值,单点查询
提示:暴力插入,然后把后面的节点全部后移,当块的大小较大后重构
Code
#include<bits/stdc++.h>
#define in(i) (i=read())
#define pr pair<int,int>
using namespace std;
const int N=5e5+10,inf=2e9;
int read() {
int ans=0,f=1; char i=getchar();
while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
while(i>='0' && i<='9') ans=(ans<<1)+(ans<<3)+(i^48),i=getchar();
return ans*f;
}
int n,m,blo,cnt;
int v[N],st[N];
vector<int>t[N];
pr find(int a) {//找到是哪个块
int x=1;
while(a>t[x].size())
a-=t[x].size(),x++;
return make_pair(x,a-1);//因为vector为0~n-1
}
void rebuild() {
cnt=0;
for(int i=1;i<=m;i++) {
for(vector<int>::iterator it=t[i].begin();it!=t[i].end();it++)
st[++cnt]=*it;
t[i].clear();
}
blo=sqrt(cnt);
for(int i=1;i<=cnt;i++)
t[(i-1)/blo+1].push_back(st[i]);
m=(cnt-1)/blo+1;
}
void insert(int a,int b) {
pr q=find(a);
t[q.first].insert(t[q.first].begin()+q.second,b);
if(t[q.first].size()>10*blo) rebuild();//重构
}
int main()
{
in(n); blo=sqrt(n);
for(int i=1;i<=n;i++) in(v[i]);
for(int i=1;i<=n;i++)
t[(i-1)/blo+1].push_back(v[i]);
m=(n-1)/blo+1;//最终块是哪个,会更新
for(int i=1;i<=n;i++) {
int op,a,b,c;
in(op),in(a),in(b),in(c);
if(!op) insert(a,b);
else {
pr q=find(b);
printf("%d\n",t[q.first][q.second]);
}
}
}
博主蒟蒻,随意转载.但必须附上原文链接
http://www.cnblogs.com/real-l/
hzwer分块九题(暂时持续更新)的更多相关文章
- 数列分块总结——题目总版(hzwer分块九题及其他题目)(分块)
闲话 莫队算法似乎还是需要一点分块思想的......于是我就先来搞分块啦! 膜拜hzwer学长神犇%%%Orz 这九道题,每一道都堪称经典,强力打Call!点这里进入 算法简述 每一次考试被炸得体无完 ...
- 知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET
知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET undefined 公司介绍 - 数人科技 undefined
- Codeforces/TopCoder/ProjectEuler/CodeChef 散题笔记 (持续更新)
最近做到了一些有趣的散题,于是开个Blog记录一下吧… (如果有人想做这些题的话还是不要看题解吧…) 2017-03-16 PE 202 Laserbeam 题意:有一个正三角形的镜子屋,光线从$C$ ...
- DP刷题记录(持续更新)
DP刷题记录 (本文例题目前大多数都选自算法竞赛进阶指南) TYVJ1071 求两个序列的最长公共上升子序列 设\(f_{i,j}\)表示a中的\(1-i\)与b中色\(1-j\)匹配时所能构成的以\ ...
- 用python做oj上的简单题(持续更新中.......)
本人刚開始接触python,在oj上解一些简单的题,欢迎交流,不喜勿喷. OJ地址链接:acm.sdut.edu.cn http://acm.sdut.edu.cn/sdutoj/showproble ...
- [LOJ] 分块九题 6
单点插入,单点查询. 优化了的链表. 链表老写错,干脆用vector,也不算慢. 注意链表退化的问题,及时(比如操作根号n次)就重新建块,实测速度可以提高一倍,这还是数据随机的情况,若涉及大量同一位置 ...
- [LOJ] 分块九题 5
区间开平方,区间查询. lazy标记改为区间是否全是1或者0,这样的区间是没有更新价值的. //Stay foolish,stay hungry,stay young,stay simple #inc ...
- leetcode腾讯精选练习(50 题)(持续更新)
1.除自身以外数组的乘积 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘 ...
- LeetCode刷题(持续更新ing……)
准备刷题了!已经预见未来的日子是苦并快乐的了!虽然 N 年前刷过题,但现在感觉数据结构与算法的基本功快忘光了
随机推荐
- (Python爬虫05)完善的爬虫学习大纲
- 将Render博客搬至GIT(偷懒)
SmallEngine 一个特别小的研究引擎[用于各种实验] 框架上设计上采用Unreal.Unity的设计思路[偷懒了] https://github.com/daozhangXDZ/DZSmall ...
- js如何判断客户端是iOS还是Android等移动终端
判断原理:JavaScript是前端开发的主要语言,我们可以通过编写JavaScript程序来判断浏览器的类型及版本.JavaScript判断浏览器类型一般有两种办法,一种是根据各种浏览器独有的属性来 ...
- 论文笔记:Deep Attentive Tracking via Reciprocative Learning
Deep Attentive Tracking via Reciprocative Learning NIPS18_tracking Type:Tracking-By-Detection 本篇论文地主 ...
- 衡量失业:失业率(Unemployment Rate)
定义 劳动力 = 就业人数 + 失业人数 失业率 = (失业人数 / 劳动力) * % 劳动力参与率 = (劳动力 / 成年人口) * %
- 《C++面试知识点》
[动态内存] 1. 由内置指针管理的动态内存(即new和delete管理动态内存),直到被显式释放之前它都是存在的.假设该指针变量被销毁,那该内存将不会自动释放(即所谓的“内存泄漏”). 2. 可以用 ...
- 默认初始化&拷贝初始化&直接初始化&值初始化&列表初始化
一.各种初始化的形式 /* 定义变量形式一:不指定初始值 */ int a; // 默认初始化 /* 定义变量形式二:指定初始值 */ int b = 1; // 拷贝初始化 int b(1); // ...
- 第一章 Windows编程基础(1~4课)
第一课:从main到WinMain 第二课:窗口和消息 第三课:MFC编程 第四课:MFC应用程序框架 概括: Win32的两种编程框架:SDK方式.MFC方式 1. SDK方式:使用WinMain入 ...
- 2017-2018-2 20172323 『Java程序设计』课程 结对编程练习_四则运算
结对编程的好丽友 - 20172323 王禹涵:中缀转后缀 - 20172314 方艺雯:后缀表达式的计算 - 20172305 谭鑫:中缀表达式的输出 需求分析 能随机生成由使用者确定的任意多道四则 ...
- python学习摘要(2)--基本数据类型
python申请存储空间是动态的.变量如同指针一样指向存储空间.多个变量会指向同一个存储空间(节省空间).当变量改变时,原来的地址单元并不会马上释放.(引用计数自行回收) c/c++根基性语言,想要什 ...