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. JAVA基础学习之路(四)定义简单java类

    简单java类开发一般原则: 类名称必须有意义,再怎么说,要让人家看的明白吧 类之中所有属性必须使用private封装,并提供setter,getter方法 类之中可以有多个构造方法,但是必须保留有一 ...

  2. hdu刷题2

    hdu1021 给n,看费波纳列数能否被3整除 算是找规律吧,以后碰到这种题就打打表找找规律吧 #include <stdio.h> int main(void) { int n; whi ...

  3. 在使用Pipeline串联多个stage时model和非model的区别

    train.csv数据: id,name,age,sex1,lyy,20,F2,rdd,20,M3,nyc,18,M4,mzy,10,M 数据读取: SparkSession spark = Spar ...

  4. LeetCode 98——验证二叉搜索树

    1. 题目 2. 解答 2.1. 方法一 我们初始化根节点的范围为长整形数据的最小最大值 \([LONG\_MIN,LONG\_MAX]\),则其左子节点的取值范围为 \([LONG\_MIN,根节点 ...

  5. Using APIs in Your Ethereum Smart Contract with Oraclize

    Homepage Coinmonks HOMEFILTER ▼BLOCKCHAIN TUTORIALSCRYPTO ECONOMYTOP READSCONTRIBUTEFORUM & JOBS ...

  6. Python3 异常与断言

    1.异常 当出现错误时,程序就会发生异常 num1=input('Please input a num1: ') num2=input('Please input a num2: ') print(f ...

  7. POJ 3304 Segments(线的相交判断)

    Description Given n segments in the two dimensional space, write a program, which determines if ther ...

  8. 微信小程序如何获取openid

    微信小程序如何获取openid wx.login({ success: res => { // 发送 res.code 到后台换取 openId, sessionKey, unionId // ...

  9. c语言乐曲演奏——《千本樱》

    这个程序着实花费了我好长的时间,我本身对音乐一窍不通,先是跟着girl friend学习了简谱,根据c调44拍的<千本樱>写下了下面的程序. #include<stdio.h> ...

  10. Hero In Maze(BFS广搜)

    Description 500年前,Jesse是我国最卓越的剑客.他英俊潇洒,而且机智过人^_^.突然有一天,Jesse心爱的公主被魔王困在了一个巨大的迷宫中.Jesse听说这个消息已经是两天以后了, ...