数列分块入门 1

题目描述:

给出一个长为 n 的数列,以及 n个操作,操作涉及区间加法,单点查值。

输入格式:

第一行输入一个数字 n。

第二行输入 n个数字,第 i个数字为 ai,以空格隔开。

接下来输入 n 行询问,每行输入四个数字 opt、l、r、c,以空格隔开。

若 opt=0,表示将位于 [l,r] 的之间的数字都加 c。

若 opt=1,表示询问 a[r] 的值(l和 c忽略)。

输出格式:

对于每次询问,输出一行一个数字表示答案。

样例输入:

4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0

样例输出:

2
5

提示:

对于 100% 的数据,1≤n≤50000,−231≤others、ans≤231−1 。

代码如下:

#include<cstdio>
const int N=1e6;
int n,a[N]={};
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	int o,l,r,c;
	for(int i=1;i<=n;i++){
		scanf("%d%d%d%d",&o,&l,&r,&c);
		if(o==1){
			printf("%d\n",a[r]);
		}else{
			for(int j=l;j<=r;j++) a[j]+=c;
		}
	}
}

但是超时了,因此本题采用分块思想。

AC代码如下:

#include<cstdio>
#include<cmath>
const int N=1e5;
int n,m,a[N]={},b[N]={},x[300]={};
int op,l,r,c;
void fun(int l,int r,int c) {
    if(b[l]==b[r]){ 
        for(int i=l;i<=r;i++) a[i]+=c;
        return;
    }
    if(l%m!=1) for(int i=l;b[i]==b[l];i++) a[i]+= c;
    else x[b[l]]+=c;
    if(r% m!=0) for(int i=r;b[i]==b[r];i--) a[i] += c;
    else x[b[r]]+=c;
    for(int i=b[l]+1;i<b[r];i++) x[i] += c;
}
int main() {
    scanf("%d", &n);
    m=sqrt(n);
    for(int i=1;i<=n;i++){ b[i]=(i-1)/m+1;scanf("%d",a+i);}
    for(int i=0;i<n;i++){
        scanf("%d%d%d%d",&op,&l,&r,&c);
        if(op==0) fun(l,r,c);
        else printf("%d\n",a[r]+x[b[r]]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值