【BZOJ2821】作诗 题解(分块+前缀和)
前言:世间还有这么卡常的题……
------------------
题目大意:给定长度为$n$的序列${a_i}$。有$m$次询问,问$[l,r]$内出现正偶数次的数字有多少个。
这题跟蒲公英有些相似,不同的是这题特别卡常……
设$sum[i][j]$表示前$i$块内$j$出现的次数,$ans[i][j]$表示块$i$到$j$的答案。
主要的问题是怎么在$O(n \sqrt n)$内进行预处理。我们采用“边扫边求”的方式来进行处理,扫的时候开一个桶,注意不要重复统计。对于$ans[i][j]$,我们有:
设$t$为块$i$到$j-1$内数$k$出现的次数。
1.如果$t$是奇数并且$bucket[k]$也是奇数,那么$ans[i][j]++$。
2.如果$t$是偶数并且$bucket[k]$是奇数,那么$ans[i][j]--$。
剩下的就跟蒲公英的处理差不多了。注意不要使用memset!!!!!!(血与泪的教训QAQ)
代码:
//求l到r中出现偶次的数字的个数
#include<bits/stdc++.h>
using namespace std;
int sum[][],ans[][];//sum 前i块中j出现的次数 ans 从i块到j块的答案
int n,m,c,a[],l,r,block,tot,t,vis[],bucket[],last;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline int getpos(int x){return (x-)/block+;}
inline void build()
{
for (int i=;i<=tot;i++)
{
for (int j=;j<=c;j++) sum[i][j]=sum[i-][j];
for (int j=(i-)*block+;j<=i*block;j++) sum[i][a[j]]++;
}
for (int i=;i<=tot;i++)
for (int j=i;j<=tot;j++)
{
ans[i][j]=ans[i][j-];
for (int k=(j-)*block+;k<=j*block;k++)
{
if (!vis[a[k]]) vis[a[k]]=,bucket[a[k]]=;
else bucket[a[k]]++;
}
for (int k=(j-)*block+;k<=j*block;k++)
{
if (!vis[a[k]]) continue;
vis[a[k]]=;
int t=sum[j-][a[k]]-sum[i-][a[k]];
if (!t){if (bucket[a[k]]%==) ans[i][j]++;}
else{
if (t%==&&bucket[a[k]]%==) ans[i][j]++;
else if (t%==&&bucket[a[k]]%==) ans[i][j]--;
}
}
}
}
inline void query()
{
int cnt=;
if (getpos(r)-getpos(l)<=)
{
for (int i=l;i<=r;i++)
{
if (!vis[a[i]]) vis[a[i]]=,bucket[a[i]]=;
else bucket[a[i]]++;
}
for (int i=l;i<=r;i++)
{
if (!vis[a[i]]) continue;
vis[a[i]]=;
if (bucket[a[i]]%==) cnt++;
}
printf("%d\n",cnt);last=cnt;
return;
}
cnt=ans[getpos(l)+][getpos(r)-];
for (int i=l;i<=getpos(l)*block;i++)
{
if (!vis[a[i]]) vis[a[i]]=,bucket[a[i]]=;
else bucket[a[i]]++;
}
for (int i=(getpos(r)-)*block+;i<=r;i++)
{
if (!vis[a[i]]) vis[a[i]]=,bucket[a[i]]=;
else bucket[a[i]]++;
}
for (int i=l;i<=getpos(l)*block;i++)
{
if (!vis[a[i]]) continue;
vis[a[i]]=;
int t=sum[getpos(r)-][a[i]]-sum[getpos(l)][a[i]];
if (!t){if (bucket[a[i]]%==) cnt++;}
else{
if (t%==&&bucket[a[i]]%==) cnt++;
if (t%==&&bucket[a[i]]%==) cnt--;
}
}
for (int i=(getpos(r)-)*block+;i<=r;i++)
{
if (!vis[a[i]]) continue;
vis[a[i]]=;
int t=sum[getpos(r)-][a[i]]-sum[getpos(l)][a[i]];
if (!t){if (bucket[a[i]]%==) cnt++;}
else{
if (t%==&&bucket[a[i]]%==) cnt++;
if (t%==&&bucket[a[i]]%==) cnt--;
}
}
printf("%d\n",cnt);last=cnt;
}
int main()
{
n=read(),c=read(),m=read();
block=sqrt(n);
tot=n/block;
if (n%block) tot++;
for (int i=;i<=n;i++) a[i]=read();
build();
for (int i=;i<=m;i++)
{
l=read(),r=read();
l=(l+last)%n+,r=(r+last)%n+;
if (l>r) swap(l,r);
query();
}
return ;
}
【BZOJ2821】作诗 题解(分块+前缀和)的更多相关文章
- BZOJ2821 作诗(Poetize) 分块
题意 算法 经验总结 代码 题意 不带修改,查询数列[1,n]中[l,r]内的出现正偶数次的数的个数, 数列中的数 <= 1e5, n <= 1e5, 强制在线 算法 查询的内容: 区 ...
- BZOJ2821 作诗(分块)
和区间众数几乎一模一样的套路. // luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include&l ...
- BZOJ2821 作诗(Poetize) 【分块】
BZOJ2821 作诗(Poetize) Description 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好是作诗. 由于时间紧迫,SHY作完诗之后还要虐OI ...
- 【BZOJ2821】作诗(Poetize) 分块
Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次, ...
- 【分块】BZOJ2821 作诗(Poetize)
2821: 作诗(Poetize) Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 3265 Solved: 951[Submit][Status][ ...
- BZOJ2821:作诗——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2821 问题描述 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好 ...
- 作诗(si)[分块]
题目描述 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好是作诗. 由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次,每次只阅读 ...
- BZOJ 2821: 作诗(Poetize)( 分块 )
分块,分成N^0.5块.O(N^1.5)预处理出sm[i][j]表示前i块中j的出现次数, ans[i][j]表示第i~j块的答案. 然后就可以O(N^0.5)回答询问了.总复杂度O((N+Q)N^0 ...
- 洛谷 P4135 作诗 题解
题面. 之前做过一道很类似的题目 洛谷P4168蒲公英 ,然后看到这题很快就想到了解法,做完这题可以对比一下,真的很像. 题目要求区间内出现次数为正偶数的数字的数量. 数据范围1e5,可以分块. 我们 ...
随机推荐
- [JAVA]枚举类型的应用
本文介绍枚举类的概念和开发过程中枚举的用法. 枚举类使用enum关键字定义,enum默认继承自Enum类,由于java单继承的特点,enum类无法再继承其他父类 一.枚举类的特性 1.简单枚举类的定义 ...
- 记一次线上服务CPU 100%的处理过程
告警 正在开会,突然钉钉告警声响个不停,同时市场人员反馈客户在投诉系统登不进了,报504错误.查看钉钉上的告警信息,几台业务服务器节点全部报CPU超过告警阈值,达100%. 赶紧从会上下来,SSH登录 ...
- python数据处理(四)之数据获取与存储
1.前烟 几个数据问题 1.1 是否能够联系上作者本人 1.2 数据是否定期检查错误并更新 1.3 数据是否包含数据获取方法的信息,是否包含数据获取过程中使用的样本类型 1.4 有没有其他数据源可以验 ...
- flask 源码专题(五):SqlAlchemy 中操作数据库时session和scoped_session的区别
1原生session: from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalc ...
- java 基本语法(十一) 数组(四)数组的常见算法
1.数组的创建与元素赋值: 杨辉三角(二维数组).回形数(二维数组).6个数,1-30之间随机生成且不重复. 杨辉三角 public class YHSJ { public static void m ...
- 数据可视化之PowerQuery篇(二十)如何计算在职员工数量?
https://zhuanlan.zhihu.com/p/128652582 经常碰到的一类问题是,如何根据起止日期来计算某个时间点的数量,比如: 已知合同的生效日期和到期日期,特定日期的有效合同有 ...
- Mybatis执行流程浅析(附深度文章推荐&面试题集锦)
首先推荐一个简单的Mybatis原理视频教程,可以作为入门教程进行学习:点我 (该教程讲解的是如何手写简易版Mybatis) 执行流程的理解 理解Mybatis的简单流程后自己手写一个,可以解决百分之 ...
- C/C++中的 if(指针变量) 和 if(!指针变量)
目录 if(指针变量) 代码演示 if(指针变量) 解读代码 if(!指针变量) 解读代码 总结 替代方案.推荐写法!!!!! if(指针变量) 当把一个指针作为条件表达式时,所要判断的条件实际上就是 ...
- ajax根据坐标查询WMS地图服务属性信息
<html lang="en"> <head> <meta charset="UTF-8"> <meta name=& ...
- Ethical Hacking - GAINING ACCESS(4)
SERVER SIDE ATTACKS - METASPLOIT Metasploit is an exploit development and execution tool. It can als ...