【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,可以分块. 我们 ...
随机推荐
- Vue 的响应式原理中 Object.defineProperty 有什么缺陷?
Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历.Proxy可以劫持整个对象,并返回一个新的对象. Proxy不仅 ...
- 机器学习实战基础(二十四):sklearn中的降维算法PCA和SVD(五) PCA与SVD 之 重要接口inverse_transform
重要接口inverse_transform 在上周的特征工程课中,我们学到了神奇的接口inverse_transform,可以将我们归一化,标准化,甚至做过哑变量的特征矩阵还原回原始数据中的特征矩阵 ...
- 数据可视化之DAX篇(八) DAX学习:使用VAR定义变量
https://zhuanlan.zhihu.com/p/64414205 前面介绍如何使用DAX生成日期表的时候,使用了VAR,有人留言问这个VAR怎么理解,那么这篇文章就来介绍VAR以及它的用法. ...
- AcWing 1208. 翻硬币
AcWing 1208. 翻硬币 原题链接 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能 ...
- SpringBoot2.x入门:使用CommandLineRunner钩子接口
前提 这篇文章是<SpringBoot2.x入门>专辑的第6篇文章,使用的SpringBoot版本为2.3.1.RELEASE,JDK版本为1.8. 这篇文章主要简单聊聊钩子接口Comma ...
- Redis之对象
1.对象的类型与编码 Redis使用对象来表示数据库中的键和值,每次我们在Redis的数据库中新创建一个键值对,我们至少会创建两个对象,一个键对象,另一个值对象. 每个对象都由一个redisObjec ...
- Ethical Hacking - NETWORK PENETRATION TESTING(7)
Gaining Access to encrypted networks Three main encryption types: 1. WEP 2.WPA 3.WPA2 WEP Cracking W ...
- Python 如何生成 200 个激活码
请用 Python 如何生成 200 个激活码. 激活码的格式为asqE-9xRK-lqWU-QkMT 要求1: 使用随机生成时,生成数字概率为1/5,大写字母和小写字母概率各为2/5 要求2: 这2 ...
- noi-vim配置
colorscheme ron set t_Co=256 set mouse=a set ts=4 set sw=4 set nu set ru set ai set ci set cin set l ...
- Linux安装禅道项目管理软件
1.从官网上面下载禅道的rpm文件 #wget http://dl.cnezsoft.com/zentao/7.1/zentaopms-7.1.stable-1.noarch.rpm 2.用指令安装 ...