CodeChef Chef and Churu [分块]
题意:
单点修改$a$
询问$a$的区间和$f$的区间和
原来普通计算机是这道题改编的吧...
对$f$分块,预处理$c[i][j]$为块i中$a_j$出现几次,$O(NH(N))$,只要每个块差分加上然后扫一遍就行了不用树状数组之类的
修改,整块直接改,还要单点修改$a$
查询,整块直接查,两边暴力查询$a$的区间和
对$a$的操作可以用树状数组,也可以再分块维护前缀和实现$O(N)-O(1)$
这样不用带一个log总复杂度$O(NH(N))$
实测快了0.4s
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e5+,M=;
typedef unsigned long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,Q,op,x,y;
ll a[N],s[N];
int pos[N],m,block;
struct _Block{int l,r;} b[M], f[N];
inline void iniBlock(){
block=sqrt(n); m=(n-)/block+;
for(int i=;i<=n;i++) pos[i]=(i-)/block+;
for(int i=;i<=m;i++) b[i].l=(i-)*block+,b[i].r=i*block;
b[m].r=n;
}
struct BlockA{
ll add[M];
void Add(int x,ll v){
for(int i=x;i<=b[pos[x]].r;i++) s[i]+=v;
for(int i=pos[x]+;i<=m;i++) add[i]+=v;
}
ll fun(_Block &x){
return s[x.r]+add[ pos[x.r] ] - (s[x.l-]+add[ pos[x.l-] ]);
}
}A;
struct Block{
int c[M][N],s[N];
ll sum[N];
void ini(){
for(int i=;i<=m;i++){
for(int j=b[i].l ; j<=b[i].r ; j++)
s[ f[j].l ]++,s[ f[j].r+ ]--;
int *cc=c[i];
for(int j=;j<=n;j++)
cc[j]=cc[j-]+s[j],sum[i]+=cc[j]*a[j],s[j]=;
}
}
void cha(int x,ll v){
ll t=v-a[x]; A.Add(x,t);
for(int i=;i<=m;i++) sum[i]+=c[i][x]*t;
a[x]=v;
}
ll que(int l,int r){
ll re=;
if(pos[l]==pos[r])
for(int i=l;i<=r;i++) re+=A.fun(f[i]);
else{
for(int i=pos[l]+;i<=pos[r]-;i++) re+=sum[i];
for(int i=l;i<=b[pos[l]].r;i++) re+=A.fun(f[i]);
for(int i=b[pos[r]].l;i<=r;i++) re+=A.fun(f[i]);
}
return re;
}
}B;
int main(){
freopen("in","r",stdin);
n=read();
for(int i=;i<=n;i++) a[i]=read(),s[i]=s[i-]+a[i];
for(int i=;i<=n;i++) f[i].l=read(),f[i].r=read();
iniBlock();B.ini();
Q=read();
while(Q--){
op=read();x=read();y=read();
if(op==) B.cha(x,y);
else printf("%llu\n",B.que(x,y));
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define pii pair<int,int>
#define MP make_pair
#define fir first
#define sec second
const int N=1e5+,M=;
typedef unsigned long long ll;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,Q,op,x,y;
ll a[N];
pii f[N];
struct BIT{
ll c[N];
inline void add(int p,ll v){for(;p<=n;p+=(p&-p)) c[p]+=v;}
inline ll sum(int p){ll re=;for(;p;p-=(p&-p)) re+=c[p];return re;}
}C;
inline ll fun(int x){return C.sum(f[x].sec)-C.sum(f[x].fir-);}
struct _Block{int l,r;ll sum;};
struct Block{
int block,m,pos[N],c[M][N],s[N];
_Block b[M];
void ini(){
block=sqrt(n); m=(n-)/block+;
for(int i=;i<=n;i++) pos[i]=(i-)/block+; for(int i=;i<=m;i++){
b[i].l=(i-)*block+; b[i].r= i==m ? n : i*block;
for(int j=b[i].l ; j<=b[i].r ; j++)
s[ f[j].fir ]++,s[ f[j].sec+ ]--;
int *cc=c[i];
for(int j=;j<=n;j++) cc[j]=cc[j-]+s[j],b[i].sum+=cc[j]*a[j],s[j]=;
}
}
void cha(int x,ll v){
v-=a[x];
for(int i=;i<=m;i++) b[i].sum+=c[i][x]*v;
C.add(x,v); a[x]+=v;
}
ll que(int l,int r){
ll re=;
if(pos[l]==pos[r])
for(int i=l;i<=r;i++) re+=fun(i);
else{
for(int i=pos[l]+;i<=pos[r]-;i++) re+=b[i].sum;
for(int i=l;i<=b[pos[l]].r;i++) re+=fun(i);
for(int i=b[pos[r]].l;i<=r;i++) re+=fun(i);
}
return re;
}
}B;
int main(){
freopen("in","r",stdin);
n=read();
for(int i=;i<=n;i++) a[i]=read(),C.add(i,a[i]);
for(int i=;i<=n;i++) f[i].fir=read(),f[i].sec=read();
B.ini();
Q=read();
while(Q--){
op=read();x=read();y=read();
if(op==) B.cha(x,y);
else printf("%llu\n",B.que(x,y));
}
}
BIT
CodeChef Chef and Churu [分块]的更多相关文章
- 【Codechef-Hard】Chef and Churu 分块
题目链接: https://www.codechef.com/problems/FNCS Solution 大力分块.. 对序列分块,维护块内前缀和.块的前缀和,修改时暴力维护两个前缀和,询问单点答案 ...
- chef and churu 分块 好题
题目大意 有一个长度为n的数组A 有n个函数,第i个函数 \[f(l[i],r[i])=\sum_{k=l[i]}^{r[i]}A_k\] 有两种操作: 1)修改A[i] 2)询问第x-y个函数值的和 ...
- Codechef FNCS Chef and Churu
Disciption Chef has recently learnt Function and Addition. He is too exited to teach this to his fri ...
- CodeChef:Chef and Problems(分块)
CodeChef:Chef and Problems 题目大意 有一个长度为n的序列$a_1,a_2,……,a_n$,每次给出一个区间[l,r],求在区间内两个相等的数的最远距离($max(j-i,满 ...
- [CC-FNCS]Chef and Churu
[CC-FNCS]Chef and Churu 题目大意: 一个长度为\(n(n\le10^5)\)的数列\(A_{1\sim n}\),另有\(n\)个函数,第\(i\)个函数会返回数组中标号在\( ...
- 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu
https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...
- CodeChef - FNCS Chef and Churu(分块)
https://vjudge.net/problem/CodeChef-FNCS 题意: 思路: 用分块的方法,对每个函数进行分块,计算出该分块里每个数的个数,这样的话也就能很方便的计算出这个分块里所 ...
- 【xsy2111】 【CODECHEF】Chef and Churus 分块+树状数组
题目大意:给你一个长度为$n$的数列$a_i$,定义$f_i=\sum_{j=l_i}^{r_i} num_j$. 有$m$个操作: 操作1:询问一个区间$l,r$请你求出$\sum_{i=l}^{r ...
- CODECHEF Chef and Churus 解题报告
[CODECHEF]Chef and Churus Description 有一个长度为\(n\)的数组\(A\),有\(n\)个函数,第\(i\)个函数的值为\(\sum_{j=l_i}^{r_i} ...
随机推荐
- c语言基础学习09_关于复合类型的复习
=============================================================================struct A{ char array[10 ...
- linphone-android-客户端APP-工程解读
LinphoneLauncherActivity 是APP的入口组件,在这个组件里,它会启动LinphoneService这个后台服务,然后不断地判断这个后台服务是否已经启动完毕,如果已经启动完毕后, ...
- Git服务搭建及github使用教程
.pos { position: fixed; top: 35%; left: 90% } .pos a { border: 2px solid white; background: #99CCFF; ...
- [学习OpenCV攻略][003[初试牛刀——显示图片]
cvLoadImage(路径) 加载指定路径的图片到内存 cvNamedWindow("窗口名称", 属性) 创建窗口,窗口名称用来被其他函数引用,属性:0表示窗口大小不变,CV_ ...
- Python3 的注释
单行注释 # 这是一个注释 print("Hello, World!") 多行注释 1:3个单引号 ''' 这是多行注释,用三个单引号 这是多行注释,用三个单引号 这是多行注释,用 ...
- vue源码入口文件分析
开发vue项目有段时间了, 之前用angularjs 后来用 reactjs 但是那时候一直没有时间把自己看源码的思考记录下来,现在我不想再浪费这 来之不易的思考, 我要坚持!! 看源码我个人感觉非常 ...
- java实现最小生成树的prim算法和kruskal算法
在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...
- UML图学习之三 状态图
状态图(Statechart Diagram)主要用于描述一个对象在其生存期间的动态行为,表现为一个对象所经历的状态序列,引起状态转移的事件(Event),以及因状态转移而伴随的动作(Action). ...
- start tomcat with debugging mode
For this, you must run your application in debug mode, which requires below parameters. -Xdebug -Xru ...
- 懒人小技巧, Toad 常用偷懒方法
用toad很久了, 感叹它的功能强大的同时整理了一些相关技巧, 有以前在网上看到的也有自己平时用的时候偶尔发现的, 分享一下, 它对用户体验方面做的真的很到位, 通过各种方式来方便用户的操作. 菜鸟 ...