zoukankan      html  css  js  c++  java
  • [Codevs] 1081 线段树练习 2 ----“分块!”

    1081 线段树练习 2

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 大师 Master
     
     
    题目描述 Description

    给你N个数,有两种操作


    1:给区间[a,b]的所有数都增加X

    2:询问第i个数是什么?

    输入描述 Input Description

    第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

     
    输出描述 Output Description

    对于每个询问输出一行一个答案

     
    样例输入 Sample Input

    3

    1 2 3

    2

    1 2 3 2

    2 3

     
    样例输出 Sample Output

    5

     
    数据范围及提示 Data Size & Hint

    数据范围

    1<=n<=100000

    1<=q<=100000

    分析 Analysis

    qwq阔别一年,终于能用分块写啦!

    这段时间在网上翻了一些博客,也翻了蓝书和ACM模版小红书,发现分块写法风格实在是多样

    像ACM红书(就清华大学出版社+俞勇主编那本ACMXXX《算法与实现》),里面写成了纯链表

    蓝书写的就比较接近我现在的习惯,但是也是难以模仿

    现在的分块类型总结如下:

    A. 将数据完全存在各种块中(就是红书那种块状链表,一个节点保存一块的信息)

    B. 将数据存在线性数组中,分块相关的附属信息用另外一个结构存,线性数组中每一个元素有对应的块编号

    个人觉得B. 比较好写(其实是因为B.写对了)

    个人觉得写的比较好的分块范例是在 1081线段树练习2 的题解里找到的,推荐!

    显然,分块的风格还是挺多的

    之前也听学长说分块很难写(因为细节部分容易出错)还难调(我是挺难调的= =)

    不过还是推荐学一学

    代码 Code

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<iostream>
     4 #define maxn 1000000
     5 using namespace std;
     6 
     7 int size,arr[maxn],block[maxn],add[maxn],n,q,swi,a,b,c;
     8 
     9 void modify(int a,int b,int c){
    10     a--,b--;
    11     for(int i = a;i <= min(block[a]*size-1,b);i++)
    12         arr[i] += c;
    13     if(block[a] != block[b]){
    14         for(int i = (block[b]-1)*size;i <= b;i++)
    15             arr[i] += c;
    16     }
    17     for(int i = block[a]+1;i < block[b];i++)
    18         add[i] += c;
    19 }
    20 
    21 int main(){
    22     scanf("%d",&n);
    23     size = (int)sqrt(n);
    24     for(int i = 0;i < n;i++) scanf("%d",&arr[i]);
    25     for(int i = 0;i < n;i++) block[i] = i/size+1;
    26 //    for(int i = 0;i < n;i++) printf("#%d: block->%d
    ",i+1,block[i]);
    27     scanf("%d",&q);
    28     for(int i = 1;i <= q;i++){
    29         scanf("%d",&swi);
    30         if(swi%2){
    31             scanf("%d%d%d",&a,&b,&c);
    32 //            for(int i = 1;i <= n;i++) printf("#%d: add->%d
    ",i,add[block[i]]);
    33             modify(a,b,c);
    34         }else{
    35             scanf("%d",&a);
    36             printf("%d
    ",arr[a-1]+add[block[a-1]]);
    37         }
    38     }
    39     
    40 //    for(int i = 0;i < n;i++) printf("#%d: block[%d]
    ",i,block[i]);
    41     
    42     return 0;
    43 }
    分块!
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    odoo10学习笔记十二:web controller
    odoo10学习笔记十一:视图综述
    odoo10学习笔记十:Actions
    odoo10学习笔记九:Odoo10 API
    odoo10学习笔记八:qweb引擎
    knockoutjs data-bind 声明式绑定整理
    使用mpvue开发小程序教程(六)
    使用mpvue开发小程序教程(五)
    使用mpvue开发小程序教程(四)
    使用mpvue开发小程序教程(三)
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7512248.html
Copyright © 2011-2022 走看看