• 【分块】一


    开了分块专题啊嘤嘤嘤一共九道题嗷呜。

    感谢黄哲威学长2333(原题都来源于他的博客)

    http://hzwer.com/8053.html

    可爱的老师要求我们每个小组都要准备一道题目的题面and题解(所以以下题目和题解均原创,然而只有标程是我原创的)

    题目和题解的来源:老王小组(万分感谢2333虽然你看不到)

    ------切入正题-----

    Z的课堂检测(test)

    (test.cpp/c/pas)

    题目描述

    大家都知道小Z的课总是十分快的(鬼知道为什么),然后我们阿M同学总是在上课时处于神游状态亦或是休眠状态,所以她对小Z到底讲了什么是一无所知。然而,小Z总是很坏地打断阿M的休眠状态,并问她问题。作为阿M的开黑好伙伴,你当然不希望阿M同学翻车(不然下一个回答问题的人就是你啦)。所以你需要编写个程序帮助阿M求小Z对于知识点到底讲的档次有多深。已知小Z在课上总会扯到涉及到N个知识点,小Z会进行M个动作(讲课或是提问阿M)。由于小Z比较古灵精怪,所以小Z的讲课时只会讲连续的知识点,并且对于这段区间内的知识点都提升一样的档次。而且,小Z也比较懒,所以小Z只会问阿M关于某一个知识点的了解程度。

    输入描述

    第一行读入N,表示小Z要涉及到N个知识点

    第二行读入A[1],A[2]……A[N-1],A[N]表示小Z上几节课已经把第i个知识点的 难度提升到A[i]的难度

    第三行读入M,表示小Z要进行M个动作

    接下来M行,读入Choice

    Choice=1,则表示小Z要讲课啦

    接下来读入L,R,X 表示小Z要对LR这些连续的知识点提升难度X

    Choice=2,则表示小Z要提问啦

    接下来读入K,表示小Z问阿MK个知识点他已经讲到哪个难度了

    输入描述

    每行输出一个数表示阿M应该回答的正确答案

    样例输入1

    10

    1 2 3 4 5 6 7 8 9 10

    5

    1 2 3 4

    2 3

    1 3 4 5

    2 5

    1 5 8 5

    样例输出1

    7

    5

    样例输入2

    7

    5 3 7 7 5 8 5

    9

    1 2 7 -1

    2 1

    2 2

    1 2 3 1

    1 2 7 2

    2 2

    1 3 3 -1

    2 3

    2 1

    样例输出2

    5

    2

    5

    8

    5

    数据范围

    对于50%的数据,N<=1000,M<=1000

    对于100%的数据,N<=100000,M<=100000 |X|<=50000

    |A[i]|<=50000;

    (觉得太烦的直接看下面)

    【简要】

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

    【解析】

    这是一道能用许多数据结构优化的经典题,可以用于不同数据结构训练。

    数列分块就是把数列中每m个元素打包起来,达到优化算法的目的。

     

    以此题为例,如果我们把每m个元素分为一块,共有n/m块,每次区间加的操作会涉及O(n/m)个整块,以及区间两侧两个不完整的块中至多2m个元素。

    我们给每个块设置一个加法标记(就是记录这个块中元素一起加了多少),每次操作对每个整块直接O(1)标记,而不完整的块由于元素比较少,暴力修改元素的值。

    每次询问时返回元素的值加上其所在块的加法标记。

    这样每次操作的复杂度是O(n/m)+O(m),根据均值不等式,当m取√n时总复杂度最低,为了方便,我们都默认下文的分块大小为√n。

    代码如下

     1 var
     2  n,n2,m,i,x,l,r,k:longint;
     3  flag:array[0..100005]of longint;
     4  f,a:array[0..100005]of int64;
     5 function min(a,b:longint):longint;
     6 begin
     7  if a>b then exit(b) else exit(a);
     8 end;
     9 procedure add(l,r,k:longint);
    10 var i:longint;
    11 begin
    12  for i:=l to min(flag[l]*n2,r) do
    13   a[i]:=a[i]+k;
    14  if flag[l]<>flag[r] then
    15   begin
    16    for i:=(flag[r]-1)*n2+1 to r do
    17     a[i]:=a[i]+k;
    18   end;
    19  for i:=flag[l]+1 to flag[r]-1 do
    20   f[i]:=f[i]+k;
    21 end;
    22 begin
    23  read(n);
    24  n2:=trunc(sqrt(n));
    25  for i:=1 to n do read(a[i]);
    26  for i:=1 to n do flag[i]:=(i-1) div n2+1;
    27  read(m);
    28  while m>0 do
    29   begin
    30    read(x);
    31    if x=1 then
    32     begin
    33      read(l,r,k);
    34      add(l,r,k);
    35     end
    36      else
    37        begin
    38         read(k);
    39         writeln(a[k]+f[flag[k]]);
    40        end;
    41    dec(m);
    42   end;
    43 end.

    2333像我这么懒的人居然还会写题解当然是自(bei)愿(po)的啊

    看看其他组题面题解什么的都写完然而我们组刚刚开始。

    该说什么比较好 (绝望)

    而且感觉分块题用pascal简直是搞疯我,当然上面那道还算正常嘤嘤嘤。

    五月都快结束了呢。

    By Hathaway 2017-05-23

  • 相关阅读:
    C# 控制反转(IOC: Inverse Of Control) & 依赖注入(DI: Independence Inject)
    英语常见短语汇总001
    ASP.Net Web.config 中引用外部config文件
    CSS样式汇总
    RSA非对称加密算法
    排序算法【2】——快速排序
    cmake引入boost
    boost之algorithm
    tar命令
    欧拉定理
  • 原文地址:https://www.cnblogs.com/Hathawaxy/p/6894800.html
Copyright © 2020-2023  润新知