洛谷 P4135 作诗(分块)
题意:\(n\) 个数,每个数都在 \([1,c]\) 中,\(m\) 次询问,每次问在 \([l,r]\) 中有多少个数出现偶数次。强制在线。
\(1 \leq n,m,c \leq 10^5\)
如果不强制在线的话可以想到莫队,关键这个强制在线怎么处理。
很容易想到对原数列进行根号分块,为了方便表示,定义 \(L_i\) 为第 \(i\) 块的左端点,\(R_i\) 为第 \(i\) 块的右端点。
我们记 \(t_{i,j}\) 表示在 \([L_i,n]\) 中 \(j\) 这个数出现了多少次,\(f_{i,j}\) 表示在 \([L_i,R_j]\) 有多少个数出现次数为偶数。
我还是太 naive 了,一看到这个“区间”就想着用区间 dp 的方式进行转移,复杂度爆炸。
事实上,我们可以在求出 \(t\) 的同时求出 \(f\)。枚举起点块 \(i\),定义 \(num\) 记录有多少个数出现了偶数次,一边往后扫一遍更新 \(num\)。
查询区间 \([l,r]\) 的时候,如果 \(l,r\) 在同一块中,直接暴力查找就行了。
如果 \([l,r]\) 不在同一块中,记 \(l'\) 为 \(l\) 所在的块,\(r'\) 为 \(r\) 所在的块,那么我们先将 \(ans\) 赋值为 \(f_{l'+1,r'-1}\),然后对于 \([l,R_{l'}] \cup [L_{r'},r]\) 中所有不同的数 \(x\),分出以下三种情况:
- \(x\) 在 \([L_{l'+1},R_{r'-1}]\) 中出现次数为不为零的偶数,但是在 \([l,r]\) 中出现次数为奇数,则表明它被算在了 \(ans\) 中,但实际不符合条件,让 \(ans\) 减一
- \(x\) 在 \([L_{l'+1},R_{r'-1}]\) 中出现次数奇数,但是在 \([l,r]\) 中出现次数为偶数,则表明它没有被算在了 \(ans\) 中,但实际符合条件,让 \(ans\) 加一
- \(x\) 在 \([L_{l'+1},R_{r'-1}]\) 中没出现过,但是在 \([l,r]\) 中出现次数为偶数,让 \(ans\) 加 \(1\)。
//Coded by tzc_wk
/*
数据不清空,爆零两行泪。
多测不读完,爆零两行泪。
边界不特判,爆零两行泪。
贪心不证明,爆零两行泪。
D P 顺序错,爆零两行泪。
大小少等号,爆零两行泪。
变量不统一,爆零两行泪。
越界不判断,爆零两行泪。
调试不注释,爆零两行泪。
溢出不 l l,爆零两行泪。
*/
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a) a.begin(),a.end()
#define giveup(...) return printf(__VA_ARGS__),0;
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,0x3f,sizeof(a))
#define fillsmall(a) memset(a,0xcf,sizeof(a))
#define mask(a) (1ll<<(a))
#define maskx(a,x) ((a)<<(x))
#define _bit(a,x) (((a)>>(x))&1)
#define _sz(a) ((int)(a).size())
#define filei(a) freopen(a,"r",stdin);
#define fileo(a) freopen(a,"w",stdout);
#define fileio(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
#define put(x) putchar(x)
#define eoln put('\n')
#define space put(' ')
#define y1 y_chenxiaoyan_1
#define y0 y_chenxiaoyan_0
typedef pair<int,int> pii;
inline int read(){
int x=0,neg=1;char c=getchar();
while(!isdigit(c)){
if(c=='-') neg=-1;
c=getchar();
}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x*neg;
}
inline void print(int x){
if(x<0){
putchar('-');
print(abs(x));
return;
}
if(x<=9) putchar(x+'0');
else{
print(x/10);
putchar(x%10+'0');
}
}
inline int qpow(int x,int e,int _MOD){
int ans=1;
while(e){
if(e&1) ans=ans*x%_MOD;
x=x*x%_MOD;
e>>=1;
}
return ans;
}
const int BLOCK_SZ=320;
int n=read(),c=read(),m=read(),a[100005],cnt[322][100005],sum[322][322];
int blk,L[322],R[322],bel[100005];
int vis[100005];
inline void prework(){
blk=(n-1)/BLOCK_SZ+1;
fz(i,1,blk){
L[i]=(i-1)*BLOCK_SZ+1;
R[i]=min(i*BLOCK_SZ,n);
fz(j,L[i],R[i]){
bel[j]=i;
}
}
fz(i,1,blk){
int num=0;
fill0(vis);
fz(j,L[i],n){
cnt[i][a[j]]++;
if(!vis[a[j]]) vis[a[j]]=1,num++;
if(cnt[i][a[j]]&1) num--;
else num++;
if(bel[j]!=bel[j+1]) sum[i][bel[j]]=num;
}
}
}
int cntt[100005];
inline int query(int l,int r){
if(bel[l]==bel[r]){
int ans=0;
fz(i,l,r) cntt[a[i]]++;
fz(i,l,r){
if(!vis[a[i]]){
if(cntt[a[i]]&1^1) ans++;
vis[a[i]]=1;
}
}
fz(i,l,r) cntt[a[i]]--,vis[a[i]]=0;
return ans;
}
else{
int l0=bel[l],r0=bel[r];
fz(i,l,R[l0]) cntt[a[i]]++;
fz(i,L[r0],r) cntt[a[i]]++;
int ans=sum[l0+1][r0-1];
fz(i,l,R[l0]){
if(!vis[a[i]]){
if((cnt[l0+1][a[i]]-cnt[r0][a[i]])>0){
if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)
ans++;
if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)
ans--;
}
else{
if((cntt[a[i]]&1)^1) ans++;
}
vis[a[i]]=1;
}
}
fz(i,L[r0],r){
if(!vis[a[i]]){
if((cnt[l0+1][a[i]]-cnt[r0][a[i]])>0){
if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)
ans++;
if(((cntt[a[i]]+cnt[l0+1][a[i]]-cnt[r0][a[i]])&1)&&(cnt[l0+1][a[i]]-cnt[r0][a[i]])&1^1)
ans--;
}
else{
if(cntt[a[i]]&1^1) ans++;
}
vis[a[i]]=1;
}
}
fz(i,l,R[l0]) cntt[a[i]]--,vis[a[i]]=0;
fz(i,L[r0],r) cntt[a[i]]--,vis[a[i]]=0;
return ans;
}
}
signed main(){
fz(i,1,n) a[i]=read();
prework();
fill0(vis);
int anss=0;
while(m--){
int l=read(),r=read();
l=(l+anss)%n+1,r=(r+anss)%n+1;
if(l>r) swap(l,r);
anss=query(l,r);
cout<<anss<<endl;
}
return 0;
}
洛谷 P4135 作诗(分块)的更多相关文章
- 洛谷P4135 作诗 (分块)
洛谷P4135 作诗 题目描述 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好是作诗. 由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章 ...
- 洛谷 P4135 作诗 题解
题面. 之前做过一道很类似的题目 洛谷P4168蒲公英 ,然后看到这题很快就想到了解法,做完这题可以对比一下,真的很像. 题目要求区间内出现次数为正偶数的数字的数量. 数据范围1e5,可以分块. 我们 ...
- 洛谷P4135 作诗(不一样的分块)
题面 给定一个长度为 n n n 的整数序列 A A A ,序列中每个数在 [ 1 , c ] [1,c] [1,c] 范围内.有 m m m 次询问,每次询问查询一个区间 [ l , r ] [l, ...
- 洛谷P4135 作诗
题意:[l,r]之间有多少个数出现了正偶数次.强制在线. 解:第一眼想到莫队,然后发现强制在线...分块吧. 有个很朴素的想法就是蒲公英那题的套路,做每块前缀和的桶. 然后发现这题空间128M,数组大 ...
- 洛谷 P4135 作诗
分块大暴力,跟区间众数基本一样 #pragma GCC optimize(3) #include<cstdio> #include<algorithm> #include< ...
- P4135 作诗——分块
题目:https://www.luogu.org/problemnew/show/P4135 分块大法: 块之间记录答案,每一块记录次数前缀和: 注意每次把桶中需要用到位置赋值就好了: 为什么加了特判 ...
- 洛谷P4198 楼房重建 (分块)
洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...
- 洛谷P3247 [HNOI2016]最小公倍数 [分块,并查集]
洛谷 思路 显然,为了达到这个最小公倍数,只能走\(a,b\)不是很大的边. 即,当前询问的是\(A,B\),那么我们只能走\(a\leq A,b\leq B\)的边. 然而,为了达到这最小公倍数,又 ...
- 洛谷P4135 Ynoi2016 掉进兔子洞 (带权bitset?/bitset优化莫队 模板) 题解
题面. 看到这道题,我第一反应就是莫队. 我甚至也猜出了把所有询问的三个区间压到一起处理然后分别计算对应询问答案. 但是,这么复杂的贡献用什么东西存?难道要开一个数组 query_appear_tim ...
随机推荐
- 【UE4 C++】打印字符串与输出日志
打印屏幕 默认打印屏幕 // 打印至屏幕 FString screenMessage = "(AddOnScreenDebugMessage) Hello world!"; GEn ...
- 这样调优之后,单机也能扛下100W连接
1 模拟单机连接瓶颈 我们知道,通常启动一个服务端会绑定一个端口,例如8000端口,当然客户端连接端口是有限制的,除去最大端口65535和默认的1024端口及以下的端口,就只剩下1 024~65 53 ...
- airtext初始化(一)
- 是兄弟就来摸鱼 Scrum Meeting 博客汇总
是兄弟就来摸鱼 Scrum Meeting 博客汇总 一.Alpha阶段 第一次Scrum meeting 第二次Scrum meeting 第三次Scrum meeting 第四次Scrum mee ...
- 技术博客——微信小程序的架构与原理
技术博客--微信小程序的架构与原理 在两个月的微信小程序开发过程中,我曾走了不少弯路,也曾被很多现在看来十分可笑的问题所困扰.这些弯路与困扰,基本上都是由于当时对小程序的架构理解不够充分,对小程序的原 ...
- 软工博客之关于CSDN的移动端软件测评
关于CSDN的移动端软件测评 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 软件测评作业 我在这个课程的目标 不求变强,只求做好,成为一颗有用的 ...
- 2021.5.24考试总结 [NOIP模拟3]
带着爆0的心态考的试,没想到整了个假rk2 (炸鱼大佬wtz忒强了OTZ T1 景区路线规划 这题对刚学完概率期望的我来说简直水爆了好吗.. 因为存在时间限制,不好跑高斯消元,就直接跑dp就完了. 令 ...
- IRCUT作用
IRCUT组成原理 IRCUT由两层滤光片组成,一片红外截止或吸收滤光片和一片全透光谱滤光片 白天是红外截止滤光片工作,晚上是全透滤光片工作,白天摄像头可以接收到人眼无法识别的红外线,会导致图像与肉眼 ...
- 示波器分析I2C时序波形图
对于嵌入式开发的朋友来说,I2C协议实在是再熟悉不过了,有太多的器件,采用的都是通过I2C来进行相应的设置.今天,我们就随便聊聊这个I2C协议. I2C协议中最重要的一点是I2C地址.这个地址有7位和 ...
- STM32 PWM功能在关闭时GPIO电平不确定的情况
刚开始接触STM32,遇到一个项目中出现在产品调试中出现在关闭PWM输出时,GPIO电平有不确定的情况.在网上查阅资料发现大神们是这样解释的:PWM在一个脉冲没有结束时关闭输出,会导致GPIO电平不确 ...