zoukankan      html  css  js  c++  java
  • LOJ 6277:数列分块入门 1(分块入门)

    #6277. 数列分块入门 1

    内存限制:256 MiB时间限制:100 ms标准输入输出

    题目类型:传统评测方式:文本比较

    上传者: hzwer

    提交提交记录统计讨论

    3

    测试数据

    题目描述

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

    输入格式

    第一行输入一个数字 n。

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

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

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

    若 opt=1,表示询问 ar 的值(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,−2^31≤others 、ans≤2^31−1。

    思路

    有好多种写法,因为在学分块,就用分块来写了

    将长度为n的数组进行分块,每个块的长度len=sqrt(n),块数为n/len

    每次需要更新时,判断需要更新的区间的左右端点是不是在一个块内,如果在一个块内,直接对这个区间进行更新就好了

    如果不在一个块内,从左端点开始到左端点所在的块的最后一个元素进行数组元素的更新,然后从右端点所在块的第一个元素开始到右端点进行数组元素的更新,对于中间的那些块,用tag数组记录下这个块中的元素一共加了多少

    最后输出的时候输出当前元素的值加上该元素所在块的tag值就行了

    AC代码

    /*
    * @Author: WZY
    * @School: HPU
    * @Date:   2018-10-11 17:08:19
    * @Last Modified by:   WZY
    * @Last Modified time: 2018-10-11 19:32:23
    */
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    #include <math.h>
    #include <limits.h>
    #include <map>
    #include <stack>
    #include <queue>
    #include <vector>
    #include <set>
    #include <string>
    #include <time.h>
    #define ll long long
    #define ull unsigned long long
    #define ms(a,b) memset(a,b,sizeof(a))
    #define pi acos(-1.0)
    #define INF 0x7f7f7f7f
    #define lson o<<1
    #define rson o<<1|1
    #define bug cout<<"---------"<<endl
    #define debug(...) cerr<<"["<<#__VA_ARGS__"= "<<(__VA_ARGS__)<<" ]"<<"
    "
    const double E=exp(1);
    const int maxn=1e6+10;
    const int mod=1e9+7;
    using namespace std;
    int a[maxn];
    int blo[maxn];
    int tag[maxn];
    int block;
    inline void add(int l,int r,int c)
    {
    	// 对端点l到端点l所在块的终点进行操作
    	for(int i=l;i<=min(blo[l]*block,r);i++)
    		a[i]+=c;
    	// 如果左右端点不在一个块内,从右端点所在的块的起点到右端点进行操作
    	if(blo[l]!=blo[r])
    		for(int i=(blo[r]-1)*block+1;i<=r;i++)
    			a[i]+=c;
    	// 对中间的块用tag数组标记每个块内元素增加了多少
    	for(int i=blo[l]+1;i<=blo[r]-1;i++)
    		tag[i]+=c;
    }
    int main(int argc, char const *argv[])
    { 
    	ios::sync_with_stdio(false);
    	#ifndef ONLINE_JUDGE
    	    freopen("in.txt", "r", stdin);
    	    freopen("out.txt", "w", stdout);
    	    double _begin_time = clock();
    	#endif
    	int n;
    	int opt,l,r,c;
    	cin>>n;
    	// 每个块的长度为sqrt(n)
    	block=sqrt(n);
    	for(int i=1;i<=n;i++)
    		cin>>a[i];
    	// 计算下标1~n属于哪个块
    	for(int i=1;i<=n;i++)
    		blo[i]=(i-1)/block+1;
    	for(int i=1;i<=n;i++)
    	{
    		cin>>opt>>l>>r>>c;
    		if(opt)
    			cout<<a[r]+tag[blo[r]]<<endl;
    		else
    			add(l,r,c);
    	}
    	#ifndef ONLINE_JUDGE
    	    double _end_time = clock();
    	    printf("time = %lf ms.", _end_time - _begin_time);
    	#endif
    	return 0;
    }
  • 相关阅读:
    LG gram 双系统全指南
    离散数学读书记录
    研究小报告:掺杂硅脂对处理器散热能力的影响
    SICP 课程总结 & 复习
    maxHeap 的 python 实现
    KDD Cup 2018 冠军团队 思路分享
    mergeSort, quickSort, shellSort 的 python 实现
    数据集-搜集
    【NOIP2018模拟赛】
    【NOIP2018 模拟】
  • 原文地址:https://www.cnblogs.com/Friends-A/p/10324342.html
Copyright © 2011-2022 走看看