【分块】一

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

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

posted @ 2017-05-23 16:43  Hathawaxy  阅读(501)  评论(1编辑  收藏  举报