作为我分块入门的第一道题

这道题花了我一整天的时间才搞出来

整理一下分块很实用思路:

分块的主要思路:比如操作区间[l,r]

1.如果l,r在一个分块里或者相邻的分块里,直接暴力

2. 否则,边角块暴力+中间分块整体解决

总体时间复杂度是n√n  能承受的数据范围是100000以内, 可以说很大了

想思路的难点就在于如何预处理,讲几个常用的预处理办法:

1. F[i][j] 数组存从[i,j]的答案

2. G[i][j] 数组存的j 在块 i 里面的特征, 可以用前缀和表示

有些预处理比较有难度,比如这一题的F[i][j],要点是:不要重复劳动,不要重复走一个区域

一遍就把所有该求的东西求出来

讲几个点吧:

1. 能不用Map就不用Map ,map虽然是stl里面的很方便,但是使用一次就是logn的时间,对时间要求紧的题目就不要用了

2. 分块的几个公式不要写错

1 int n, S, N;
2 int A[maxn], ID[maxn];
3
4 S = sqrt(n);//初始化
5 N = (n-1)/S + 1;
6 for(int i = 1;i <= n;i++) {
7     scanf("%d",&A[i]);
8     ID[i] = (i-1)/S + 1;
9 }

3.O(1)初始化的技巧要会,用一个次数t来代表第几次使用cnt数组,然后把次数更新在cntM数组里面

1 if(cntM[A[i]] != t) {
2     cntM[A[i]] = t;
3     cnt[A[i]] = 0;
4 }

4.如果可以的话,快速读入也是很重要的

5. 在处理边角块的时候, for循环的使用技巧也很重要,比如跨区域扫描。

1     for(int i = x;i <= y;) {
2
3       if(i == ID[x]*S) i = (ID[y]-1)*S+1;
4         else i++;
5     }

6. 还有交换x,y变量的骚技巧:

1 x^=y^=x^=y;

完整代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<map>
  4 #include<cmath>
  5 #include<iostream>
  6 using namespace std;
  7 const int maxn = 100010;
  8 const int maxm = 333;
  9
 10 int n, m, c, S, N;
 11 int A[maxn], ID[maxn], cnt[maxn], Q[maxn], cntM[maxn];
 12 int F[maxm][maxm], G[maxm][maxn];
 13
 14 inline int query(int x,int y,int t) {
 15     int ret = 0;
 16
 17     if(ID[x] + 1 >= ID[y] ) {
 18         for(int i = x;i <= y;i++) {
 19             if(cntM[A[i]] != t) {
 20                 cntM[A[i]] = t;
 21                 cnt[A[i]] = 0;
 22             }
 23             cnt[A[i]]++;
 24             if(cnt[A[i]]%2 == 0 && cnt[A[i]] >= 2) ret++;
 25             else if(cnt[A[i]]%2 == 1 && cnt[A[i]] >= 2) ret--;
 26         }
 27         return ret;
 28     }
 29
 30     ret = F[ID[x]+1][ID[y]-1];
 31
 32
 33     for(int i = x;i <= y;) {
 34         if(cntM[A[i]] != t) {
 35                 cntM[A[i]] = t;
 36                 cnt[A[i]] = 0;
 37         }
 38         cnt[A[i]]++;
 39
 40         int tp = G[ID[y]-1][A[i]] - G[ID[x]][A[i]];
 41         int sum = tp + cnt[A[i]];
 42
 43         if(sum <= 1) {
 44             if(i == ID[x]*S) i = (ID[y]-1)*S+1;
 45             else i++;
 46             continue;
 47         }
 48
 49         if(sum%2 == 1) ret--;
 50       if(sum%2 == 0) ret++;
 51
 52       if(i == ID[x]*S) i = (ID[y]-1)*S+1;
 53         else i++;
 54     }
 55     return ret;
 56 }
 57
 58 int main() {
 59     //freopen("d.txt","r",stdin);
 60     scanf("%d %d %d",&n,&c,&m);
 61     S = sqrt(n);
 62     N = (n-1)/S + 1;
 63     for(int i = 1;i <= n;i++) {
 64         scanf("%d",&A[i]);
 65         ID[i] = (i-1)/S + 1;
 66     }
 67
 68     int sum = 0;
 69     for(int i = 1;i <= N;i++) {
 70         sum = 0;
 71         int t = i;
 72         for(int j = (i-1)*S + 1;j <= n;j++) {
 73             int p = ID[j];
 74             if(cntM[A[j]] != t) {
 75                 cntM[A[j]] = t;
 76                 cnt[A[j]] = 0;
 77             }
 78             cnt[A[j]]++;
 79             if(cnt[A[j]]%2 == 0 && cnt[A[j]] >= 2) sum++;
 80             else if(cnt[A[j]]%2 == 1 && cnt[A[j]] >= 2) sum--;
 81             if(j%S == 0 || j == n) F[i][p] = sum;
 82         }
 83     }
 84
 85   memset(cnt,0,sizeof(cnt));
 86   for(int i = 1;i <= n;i++) {
 87       cnt[A[i]]++;
 88       if(i%S == 0 || i == n) {
 89           for(int j = 1;j <= c;j++) G[ID[i]][j] = cnt[j];
 90         }
 91     }
 92
 93   int ans = 0;
 94     for(int i = 1,x,y;i <= m;i++) {
 95       scanf("%d %d",&x,&y);
 96       x=(x+ans)%n+1;
 97     y=(y+ans)%n+1;
 98     if(x>y) x^=y^=x^=y;
 99    // cout<<x<<" : "<<y<<endl;
100       ans = query(x,y,i+N);
101         printf("%d\n",ans);
102     }
103
104     return 0;
105 } 

转载于:https://www.cnblogs.com/frankscode/p/9511886.html

洛谷P4135 作诗 --分块基础相关推荐

  1. BZOJ 2821 作诗 分块

    BZOJ 2821 作诗 Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗 之后还要虐OI,于是SHY找来一 ...

  2. 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]

    洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...

  3. 洛谷 - P4168 [Violet]蒲公英(分块+离散化)

    题目链接:点击查看 题目大意:给出一个长度为 n 的数列,再给出 m 次查询,每次查询区间 [ l , r ] 内的众数,要求强制在线 题目分析:对于这个题意来说,如果允许离线的话,完全可以用莫队当模 ...

  4. 洛谷-P1903 数颜色 分块 bitset

    题目 题目链接 题意 给你一个数列代表不同的颜色(可以修改). 询问一段区间内有多少种颜色. 题解 很容易想到的就是线段树来维护bitset. 这里为了练习,使用分块维护bitset. * 事实上线段 ...

  5. 洛谷 - P3935 - Calculating - 整除分块

    https://www.luogu.org/fe/problem/P3935 求: \(F(n)=\sum\limits_{i=1}^{n}d(i)\) 枚举因子\(d\),每个因子\(d\)都给其倍 ...

  6. bzoj 2821:作诗 分块

    题目大意: 给定一个长为n的序列,每次询问一个区间内出现了偶数次的数的个数.强制在线. 题解: 据说这道题正解只用了5MB的内存 QAQ... 反正我是120MB + 卡过去的... 我们可以分块! ...

  7. 动态规划——最大子段和(洛谷 P1115)

    题目选择洛谷P1115 经典的动态规划基础题目,最大连续子序列和 状态转移方程为: dp[i] = max{A[i],dp[i-1]+A[i]} 题目描述 给出一个长度为 n 的序列 a,选出其中连续 ...

  8. [BZOJ4889][洛谷P3759][TJOI2017]不勤劳的图书管理员 分块+树状数组

    题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打乱顺序的书, ...

  9. 【题解】洛谷P4168 [Violet]蒲公英 (分块)

    [题解]洛谷P4168 [Violet]蒲公英 (分块)     D e s c r i p t i o n \rm Description Description 我们把所有的蒲公英看成一个长度为 ...

  10. 洛谷【C++编程基础】递归函数初步 专题解题报告

    洛谷[C++编程基础]递归函数初步 专题解题报告 T1-T89304 递归求和 题目描述 用递归的方法求1+2+3+4+-+(n-1)+n的值. 输入格式 一个整数n.(1<=n<=100 ...

最新文章

  1. Factory-pattern 三种工厂模式
  2. 有一台电脑怎么挣钱_大聪明,双十一我想6000元配置一台能畅玩主流游戏的电脑,应该怎么搭配?...
  3. 基于MIG控制器的DDR3读写控制详解
  4. Qt Creator美化源代码
  5. XGBoost-原理推导(上)
  6. UVa 297 四分树
  7. 一起谈.NET技术,编写T4模板无法避免的两个话题:quot;Assembly Lockingquot;amp;quot;Debugquot;...
  8. 一只青蛙跳向三个台阶_青蛙跳台阶问题的三种解法
  9. Android蓝牙A2dp profile的使用
  10. MYSQL等级考试考的是Linux吗,Linux命令行下快速监控mysql
  11. 怎样学好计算机——计算机达人成长之路(23)
  12. 贝叶斯(五)贝叶斯决策
  13. 【0代码编程】ivx简介
  14. C# ThoughtWorks.QRCode.dll 生成完美二维码(大小 边距 备注 颜色 LOGO大小背景形状)
  15. U盘装系统:魔方U盘启动制作
  16. htc 8x android,htc 8x的usb驱动下载
  17. 牛客网 KY6 手机键盘
  18. 2011计算机考研大,2011年计算机考研大纲
  19. 自定义自动统计字数EditText控件
  20. CTF Misc 题目基础

热门文章

  1. 翻车了!StackOverflow上复制最多的代码存在缺陷!
  2. 漫谈四种主流软件架构演进史
  3. 【名额有限】腾讯技术工程-运维技术沙龙
  4. 没有副业的人,太难了。。。
  5. shell基础之变量及表达式
  6. P1052 过河 线性dp
  7. DOM(一):节点层次-Node类型
  8. Git钩子:自定义你的工作流
  9. python 基础 5 while循环语句
  10. vscode过滤pyc文件