洛谷P4135 作诗 --分块基础
作为我分块入门的第一道题
这道题花了我一整天的时间才搞出来
整理一下分块很实用思路:
分块的主要思路:比如操作区间[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 作诗 --分块基础相关推荐
- BZOJ 2821 作诗 分块
BZOJ 2821 作诗 Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗 之后还要虐OI,于是SHY找来一 ...
- 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]
洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...
- 洛谷 - P4168 [Violet]蒲公英(分块+离散化)
题目链接:点击查看 题目大意:给出一个长度为 n 的数列,再给出 m 次查询,每次查询区间 [ l , r ] 内的众数,要求强制在线 题目分析:对于这个题意来说,如果允许离线的话,完全可以用莫队当模 ...
- 洛谷-P1903 数颜色 分块 bitset
题目 题目链接 题意 给你一个数列代表不同的颜色(可以修改). 询问一段区间内有多少种颜色. 题解 很容易想到的就是线段树来维护bitset. 这里为了练习,使用分块维护bitset. * 事实上线段 ...
- 洛谷 - P3935 - Calculating - 整除分块
https://www.luogu.org/fe/problem/P3935 求: \(F(n)=\sum\limits_{i=1}^{n}d(i)\) 枚举因子\(d\),每个因子\(d\)都给其倍 ...
- bzoj 2821:作诗 分块
题目大意: 给定一个长为n的序列,每次询问一个区间内出现了偶数次的数的个数.强制在线. 题解: 据说这道题正解只用了5MB的内存 QAQ... 反正我是120MB + 卡过去的... 我们可以分块! ...
- 动态规划——最大子段和(洛谷 P1115)
题目选择洛谷P1115 经典的动态规划基础题目,最大连续子序列和 状态转移方程为: dp[i] = max{A[i],dp[i-1]+A[i]} 题目描述 给出一个长度为 n 的序列 a,选出其中连续 ...
- [BZOJ4889][洛谷P3759][TJOI2017]不勤劳的图书管理员 分块+树状数组
题目描述 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打乱顺序的书, ...
- 【题解】洛谷P4168 [Violet]蒲公英 (分块)
[题解]洛谷P4168 [Violet]蒲公英 (分块) D e s c r i p t i o n \rm Description Description 我们把所有的蒲公英看成一个长度为 ...
- 洛谷【C++编程基础】递归函数初步 专题解题报告
洛谷[C++编程基础]递归函数初步 专题解题报告 T1-T89304 递归求和 题目描述 用递归的方法求1+2+3+4+-+(n-1)+n的值. 输入格式 一个整数n.(1<=n<=100 ...
最新文章
- Factory-pattern 三种工厂模式
- 有一台电脑怎么挣钱_大聪明,双十一我想6000元配置一台能畅玩主流游戏的电脑,应该怎么搭配?...
- 基于MIG控制器的DDR3读写控制详解
- Qt Creator美化源代码
- XGBoost-原理推导(上)
- UVa 297 四分树
- 一起谈.NET技术,编写T4模板无法避免的两个话题:quot;Assembly Lockingquot;amp;quot;Debugquot;...
- 一只青蛙跳向三个台阶_青蛙跳台阶问题的三种解法
- Android蓝牙A2dp profile的使用
- MYSQL等级考试考的是Linux吗,Linux命令行下快速监控mysql
- 怎样学好计算机——计算机达人成长之路(23)
- 贝叶斯(五)贝叶斯决策
- 【0代码编程】ivx简介
- C# ThoughtWorks.QRCode.dll 生成完美二维码(大小 边距 备注 颜色 LOGO大小背景形状)
- U盘装系统:魔方U盘启动制作
- htc 8x android,htc 8x的usb驱动下载
- 牛客网 KY6 手机键盘
- 2011计算机考研大,2011年计算机考研大纲
- 自定义自动统计字数EditText控件
- CTF Misc 题目基础