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分块九题(暂时持续更新)的更多相关文章

  1. 数列分块总结——题目总版(hzwer分块九题及其他题目)(分块)

    闲话 莫队算法似乎还是需要一点分块思想的......于是我就先来搞分块啦! 膜拜hzwer学长神犇%%%Orz 这九道题,每一道都堪称经典,强力打Call!点这里进入 算法简述 每一次考试被炸得体无完 ...

  2. 知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET

    知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET undefined 公司介绍 - 数人科技 undefined

  3. Codeforces/TopCoder/ProjectEuler/CodeChef 散题笔记 (持续更新)

    最近做到了一些有趣的散题,于是开个Blog记录一下吧… (如果有人想做这些题的话还是不要看题解吧…) 2017-03-16 PE 202 Laserbeam 题意:有一个正三角形的镜子屋,光线从$C$ ...

  4. DP刷题记录(持续更新)

    DP刷题记录 (本文例题目前大多数都选自算法竞赛进阶指南) TYVJ1071 求两个序列的最长公共上升子序列 设\(f_{i,j}\)表示a中的\(1-i\)与b中色\(1-j\)匹配时所能构成的以\ ...

  5. 用python做oj上的简单题(持续更新中.......)

    本人刚開始接触python,在oj上解一些简单的题,欢迎交流,不喜勿喷. OJ地址链接:acm.sdut.edu.cn http://acm.sdut.edu.cn/sdutoj/showproble ...

  6. [LOJ] 分块九题 6

    单点插入,单点查询. 优化了的链表. 链表老写错,干脆用vector,也不算慢. 注意链表退化的问题,及时(比如操作根号n次)就重新建块,实测速度可以提高一倍,这还是数据随机的情况,若涉及大量同一位置 ...

  7. [LOJ] 分块九题 5

    区间开平方,区间查询. lazy标记改为区间是否全是1或者0,这样的区间是没有更新价值的. //Stay foolish,stay hungry,stay young,stay simple #inc ...

  8. leetcode腾讯精选练习(50 题)(持续更新)

    1.除自身以外数组的乘积 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘 ...

  9. LeetCode刷题(持续更新ing……)

    准备刷题了!已经预见未来的日子是苦并快乐的了!虽然 N 年前刷过题,但现在感觉数据结构与算法的基本功快忘光了

随机推荐

  1. Zookeeper与Eureka的区别

    Zookeeper与Eureka的区别 想要了解Zk与eureka的区别首先要知道CAP定理 CAP定理 Mysql强一致性(数据唯一出处),设计数据库设计的三范式 (表必须有主键:表不能有重复的列: ...

  2. 解析Java中final关键字的各种用法

    首先,我们可以从字面上理解一下final这个英文单词的中文含义:“最后的,最终的; 决定性的; 不可更改的:”.显然,final关键词如果用中文来解释,“不可更改的”更为合适.当你在编写程序,可能会遇 ...

  3. python numpy数据相减

    numpy数据相减,a和b两者shape要一样,然后是对应的位置相减.要不然,a的shape可以是(1,m),注意m要等于b的列数. import numpy as np a = [ [0, 1, 2 ...

  4. 函数重载(overload)和函数重写(override)

    1. 前言: 在C++中有两个非常容易混淆的概念,分别是函数重载(overload)和函数重写(overwirte).虽然只相差一个字,但是它们两者之间的差别还是非常巨大的. 而通过深入了解这两个概念 ...

  5. scipy 图像处理-深度学习

    scipy 图像处理(scipy.misc.scipy.ndimage).matplotlib 图像处理 from scipy.misc import imread / imsave / imshow ...

  6. Chameleon-mini简介

    ChameleonMini(变色龙)原德国大学在研究RFID安全时所设计的一块针对多频段多类型RFID模拟的硬件,其设计本身支持ISO14443和ISO15693标准协议,最简单直接的用法就是把获取到 ...

  7. 6.azkban的监控

    azkaban自带的监控flow自带的邮件功能SLA总结写程序监控job情况监控azkaban的元数据库使用azkaban API监控总结 azkaban自带的监控 azkban目前仅仅支持邮件监控, ...

  8. Python面向对象-访问限制

    在Class内部,可以有字段,方法和属性,而外部代码可以通过直接调用实例变量的方法来操作数据, (1)私有普通字段 比如对于下面的Student类,name字段可以在外面通过对象进行直接访问: cla ...

  9. Cannot retrieve repository metadata (repomd.xml) for repository: base. Please verify its path and try again YUM报错

        1.挂盘 ----- 2.# mount /dev/sr0 /media/ mount: block device /dev/sr0 is write-protected, mounting ...

  10. 在线求助man page

    一.举例——输入“man date” 图1 图2 图3 二.man之概述 用于:命令的使用说明 用法:man 命令 man page:执行“man 命令”后,出现的屏幕界面 补:man是manual( ...