zoukankan      html  css  js  c++  java
  • 【分块】一

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

    感谢黄哲威学长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

  • 相关阅读:
    Leetcode 16.25 LRU缓存 哈希表与双向链表的组合
    Leetcode437 路径总和 III 双递归与前缀和
    leetcode 0404 二叉树检查平衡性 DFS
    Leetcode 1219 黄金矿工 暴力回溯
    Leetcode1218 最长定差子序列 哈希表优化DP
    Leetcode 91 解码方法
    Leetcode 129 求根到叶子节点数字之和 DFS优化
    Leetcode 125 验证回文串 双指针
    Docker安装Mysql记录
    vmware虚拟机---Liunx配置静态IP
  • 原文地址:https://www.cnblogs.com/Hathawaxy/p/6894800.html
Copyright © 2011-2022 走看看