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)完善的爬虫学习大纲
- (Python爬虫04)了解通用爬虫和聚焦爬虫,还是理论知识.快速入门可以略过的
如果现在的你返回N年前去重新学习一门技能,你会咋做? 我会这么干: ...哦,原来这个本事学完可以成为恋爱大神啊, 我要掌握精髓需要这么几个要点一二三四..... 具体的学习步骤是这样的一二三.... ...
- leetcode-位1的个数(位与运算)
位1的个数 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量). 示例 : 输入: 11 输出: 3 解释: 整数 11 的二进制表示为 00000 ...
- 【shell 每日一练6】初始化安装Mysql并修改密码
一.简单实现mysql一键安装 参考:[第二章]MySQL数据库基于Centos7.3-部署 此脚本前提条件是防火墙,selinux都已经设置完毕: [root@web130 ~]# cat Inst ...
- LeetCode 138——复制带随机指针的链表
1. 题目 2. 解答 第一次遍历链表的时候,复制旧链表的节点值建立一个新的链表,同时定义一个 unordered_map 作为哈希表,哈希表的键为旧链表的节点指针,值为新链表的节点指针. 然后,第二 ...
- truffle框架快速开发合约步骤
矩阵元区块链智能合约开发指南 1 适用范围 本规范描述了矩阵元区块链系统智能合约的开发约束与规范,用以指导DAPP开发者按照本规范开发基于矩阵元区块链运行的应用. 2 术语解释 术语 术语解释 DAP ...
- 深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)
转载:http://zh.lucida.me/blog/java-8-lambdas-inside-out-library-features/ 关于 深入理解 Java 8 Lambda(语言篇——l ...
- Python中除法:/和//
在Python中,除法有两种:/和//. X / Y 对于Python2.X来说,如果两个操作数都是整数,那么结果将向下取整(这个和C里面的不同,C里面是向0取整),也就是说,如果结果本来是-2.5, ...
- 2. socket结构体——表示socket地址
一.两种通用socket结构体 1. sockaddr struct sockaddr { sa_family_t sa_family; // 地址族 char sa_data[14]; // 存放s ...
- 今年暑假不AC (贪心)
Description “今年暑假不AC?” “是的.” “那你干什么呢?” “看世界杯呀,笨蛋!” “@#$%^&*%...” 确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会 ...