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 年前刷过题,但现在感觉数据结构与算法的基本功快忘光了
随机推荐
- fastCMS八大核心对象
fastCMS内置system对象,该对象包含八大核心对象,应用于不同的操作场景,分别是: 1.system.string 对象(处理字符类操作) 2.system.number 对象(处理数字类操作 ...
- Spring Cloud(十一):服务网关 Zuul(过滤器)【Finchley 版】
Spring Cloud(十一):服务网关 Zuul(过滤器)[Finchley 版] 发表于 2018-04-23 | 更新于 2018-05-07 | 在上篇文章中我们了解了 Spring ...
- ubuntu samba配置注意事项
1. 下载samba前, ubuntu镜像源需要更新为国内源,否则samba的安装会非常慢 亲测,清华的镜像源速度满足要求. A.登录 https://mirrors.tuna.tsinghua.ed ...
- 在 Ubuntu 下安装 Deepin 的 QQ、微信、百度云和迅雷等软件
在以前的文章 Ubuntu 常用软件推荐(QQ.微信.MATLAB等)及安装过程 中,我们用 Wine QQ 和 Electronic Wechat 来解决 Ubuntu 系统下使用 QQ 和微信的难 ...
- 针对“来用”团队项目之NABC分析
本项目特点之一:扩展性强 NABC分析: N(need):我们这个开发的这个软件主要是集娱乐软件和实用工具于一身的大容器,这里面有很多应用程序,针对不同用户需要,至少有一款应用程序能够满足用户的需要, ...
- bootstrap使用中遇到的坑
一.例如: <div class="form-group"> <label class="control-label col-lg-3"> ...
- C与C++,面向过程与面向对象
C与C++在电梯处理上的不同 (注:个人理解) 对比区别: C语言程序制定具体流程,按流程逐步进行. C++程序将过程结构化,需要使用时利用接口访问与调用不同功能的类结构结构. 电梯类代码 电梯类定义 ...
- iOS- NSThread/NSOperation/GCD 三种多线程技术的对比及实现
1.iOS的三种多线程技术 1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程) 2.以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题 ...
- 【week2】 词频统计效能分析
效能统计工具:Jprofiler License Key:L-Larry_Lau@163.com#23874-hrwpdp1sh1wrn#0620 该性能分析工具对服务器进行监听,图一是线程变化图,当 ...
- MySQL加密算法
1.不可逆加密: PASSWORD(),ENCRYPT(,),MD5(),SHA5(). 2.可逆的加密算法: ENCODE(,) DECODE(,):加密解密字符串.该函数有两个参数:被加密或解 ...