Codeforces #80 Div1 D 分块 题解

题目:Problem - D - Codeforces

本题目思路以分块思想为框架,而具体实现却也卡了我很久,思路参见2014年国家队集训论文集中王悦同的《根号算法——不只是分块》。

太多技巧和方法需要掌握了,路漫漫其修远兮!

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #define ll long long
 5 ll arr[300010];
 6 ll dp[300010];
 7 using namespace std;
 8 struct qujian {
 9     int a;
10     int b;
11     int id;
12     ll sum;
13     int operator<(const qujian& s)
14     {
15         return id < s.id;
16     }
17 }qujians[300010];
18 int cmpare(qujian a, qujian b)
19 {
20     return a.b < b.b;
21 }
22 
23 inline int read()//inline 加速读入
24 {
25     int x = 0;char c = getchar();//x代表返回值,c代表读取的字符
26     while (c < '0' || c>'9') c = getchar();//读取所有非数部分
27     while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();//如果读取的字符为数,加入返回值
28     return x;
29 }
30 
31 int main(void)
32 {
33     int n;
34     cin >> n;
35     for (int i = 1;i <= n;i++)
36         arr[i]=read();
37     int m;
38     cin >> m;
39     int sqr_n = sqrt(n);
40     for (int i = 1;i <= m;i++)
41     {
42         qujians[i].id = i;
43         qujians[i].a = read();
44         qujians[i].b = read();
45     }
46     //为什么要建立这样的结构体呢?因为我试过了创建一个Di[i:300010][j:600]来代表mod j后余数为i的集合,然后直接O(1)得到答案,而超了内存限制了。
47     //走qujians这条结构体是为了把输入和输出分开,对于每个b我进行一次递推,推导出每个余数的sum值,然后再赋给qujians【i】.sum。
48     //其中的两次sort来使得成功将输入和输出分离,是我学到的新东西。
49     sort(qujians, qujians + m, cmpare);
50     int b = -1;
51     for (int i = 1;i <= m;i++)
52     {
53         if (qujians[i].b < sqr_n)
54         {
55             if (qujians[i].b == b)
56                 qujians[i].sum = dp[qujians[i].a];
57             else
58             {
59                 b = qujians[i].b;
60                 for (int j = n;j > 0;j--)
61                 {
62                     if (b + j > n)
63                         dp[j] = arr[j];
64                     else
65                         dp[j] = dp[j + b] + arr[j];
66                 }
67                 //此处的递推方法也是让我耳目一新的,路漫漫其修远兮。。。
68                 qujians[i].sum = dp[qujians[i].a];
69             }
70         }
71         else
72         {
73             qujians[i].sum = 0;
74             for (int j = qujians[i].a;j <= n;j += qujians[i].b)
75                 qujians[i].sum += arr[j];
76         }
77     }
78     sort(qujians, qujians + m);
79     for (int i = 1;i <= m;i++)
80          printf("%lld\n",qujians[i].sum );
81     return 0;
82 }

 

上一篇:2022.2.28


下一篇:【算法】(Floyd算法)图的中心顶点问题(C语言)