一、区间查询+单点更新
luogu3374
已知一个数列,你需要进行下面两种操作:1.将某一个数加上x;2.求出某区间每一个数的和(luogu3374)
#include<bits/stdc++.h>
using namespace std;
#define maxn 500010
int n,m;
int num,block;//block块的大小,num分块的个数
int belong[maxn],l[maxn],r[maxn];
//belong[i]表示i属于哪一块
//l[i]表示i这块的左端点位置
//r[i]表示右端点位置
int a[maxn],mark[maxn];
int nana[maxn];//表示该块的和
void build()
{
block=sqrt(n);
num=n/block;
if(n%block)num++;
for (int i=1;i<=num;i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}//存每一块的左右端点
for (int i=1;i<=n;i++)//存分区
belong[i]=(i-1)/block+1;
for (int i=1;i<=n;i++)//求每一块的总和
nana[belong[i]]+=a[i];
}
//单点更新
void update(int pos,int x)
{
nana[belong[pos]]+=x;
a[pos]+=x;
}
//区间查询
void query(int L,int R)
{
int ans=0;
if (belong[L]==belong[R])//l,r在同一块
{
for (int i=L;i<=R;i++)
ans+=a[i];
printf("%d\n",ans);
return;
}
for (int i=L;i<=r[belong[L]];i++)//左不完整块
ans+=a[i];
for (int i=l[belong[R]];i<=R;i++)//右不完整块
ans+=a[i];
for (int i=belong[L]+1;i<belong[R];i++)//中间的完整块
ans+=nana[i];
printf("%d\n",ans);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
build();
int flag,x,y;
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&flag,&x,&y);
if (flag==2)query(x,y);
else update(x,y);
}
return 0;
}
二、区间更新+单点查询
luogu3368
已知一个数列,你需要进行下面两种操作:1.将某区间每一个数数加上x;2.求出某一个数的和
#include<bits/stdc++.h>
using namespace std;
#define maxn 500010
int n,m;
int num,block;//block块的大小,num分块的个数
int belong[maxn],l[maxn],r[maxn];
//belong[i]表示i属于哪一块
//l[i]表示i这块的左端点位置
//r[i]表示右端点位置
int a[maxn],mark[maxn];
int nana[maxn];//表示该块的和
void build()
{
block=sqrt(n);
num=n/block;
if(n%block)num++;
for (int i=1;i<=num;i++)
{
l[i]=(i-1)*block+1;
r[i]=i*block;
}//存每一块的左右端点
for (int i=1;i<=n;i++)//存分区
belong[i]=(i-1)/block+1;
}
//区间加法
void several_add(int L,int R,int k)
{
for(int i=L;i<=r[belong[L]];i++)
a[i]+=k;
if(belong[L]!=belong[R])
for(int i=l[belong[R]];i<=R;i++)
a[i]+=k;
for(int i=belong[L]+1;i<=belong[R]-1;i++)
nana[i]+=k;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
build();
int flag,x,y;
for (int i=1;i<=m;i++)
{
scanf("%d",&flag);
if (flag==2)
{
int K;
scanf("%d",&K);
printf("%d\n",a[K]+nana[belong[K]]);
}
else
{
int x,y,k;
scanf("%d %d %d",&x,&y,&k);
several_add(x,y,k);
}
}
return 0;
}
三、区间加法+区间乘法+区间点查询
luogu3373
已知一个数列,你需要进行下面三种操作:1.将某区间每一个数加上x;2.将某区间每一个数乘上x;3.求出某区间每一个数的和。