题目链接

题意:\(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\),分出以下三种情况:

  1. \(x\) 在 \([L_{l'+1},R_{r'-1}]\) 中出现次数为不为零的偶数,但是在 \([l,r]\) 中出现次数为奇数,则表明它被算在了 \(ans\) 中,但实际不符合条件,让 \(ans\) 减一
  2. \(x\) 在 \([L_{l'+1},R_{r'-1}]\) 中出现次数奇数,但是在 \([l,r]\) 中出现次数为偶数,则表明它没有被算在了 \(ans\) 中,但实际符合条件,让 \(ans\) 加一
  3. \(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 作诗(分块)的更多相关文章

  1. 洛谷P4135 作诗 (分块)

    洛谷P4135 作诗 题目描述 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好是作诗. 由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章 ...

  2. 洛谷 P4135 作诗 题解

    题面. 之前做过一道很类似的题目 洛谷P4168蒲公英 ,然后看到这题很快就想到了解法,做完这题可以对比一下,真的很像. 题目要求区间内出现次数为正偶数的数字的数量. 数据范围1e5,可以分块. 我们 ...

  3. 洛谷P4135 作诗(不一样的分块)

    题面 给定一个长度为 n n n 的整数序列 A A A ,序列中每个数在 [ 1 , c ] [1,c] [1,c] 范围内.有 m m m 次询问,每次询问查询一个区间 [ l , r ] [l, ...

  4. 洛谷P4135 作诗

    题意:[l,r]之间有多少个数出现了正偶数次.强制在线. 解:第一眼想到莫队,然后发现强制在线...分块吧. 有个很朴素的想法就是蒲公英那题的套路,做每块前缀和的桶. 然后发现这题空间128M,数组大 ...

  5. 洛谷 P4135 作诗

    分块大暴力,跟区间众数基本一样 #pragma GCC optimize(3) #include<cstdio> #include<algorithm> #include< ...

  6. P4135 作诗——分块

    题目:https://www.luogu.org/problemnew/show/P4135 分块大法: 块之间记录答案,每一块记录次数前缀和: 注意每次把桶中需要用到位置赋值就好了: 为什么加了特判 ...

  7. 洛谷P4198 楼房重建 (分块)

    洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...

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

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

  9. 洛谷P4135 Ynoi2016 掉进兔子洞 (带权bitset?/bitset优化莫队 模板) 题解

    题面. 看到这道题,我第一反应就是莫队. 我甚至也猜出了把所有询问的三个区间压到一起处理然后分别计算对应询问答案. 但是,这么复杂的贡献用什么东西存?难道要开一个数组 query_appear_tim ...

随机推荐

  1. NX屏蔽窗口的按钮

    有时候在激活一个命令按钮的时候,需要同时禁止掉另外一个或多个命令按钮 ''' <summary> ''' 取按钮是否敏感 ''' </summary> ''' <para ...

  2. gin 源码阅读(5) - 灵活的返回值处理

    gin 源码阅读系列文章列表: gin 源码阅读(1) - gin 与 net/http 的关系 gin 源码阅读(2) - http请求是如何流入gin的? gin 源码阅读(3) - gin 路由 ...

  3. 盘点一下Redis中常用的Java客户端,或者咱们手写一个?

    Java中那些Redis的客户端 前面我们的所有操作都是基于redis-cli来完成的,那么我们要在Java中操作Redis,怎么做呢?首先我们先来了解一下Redis Serialization Pr ...

  4. 【数据结构与算法Python版学习笔记】递归(Recursion)——定义及应用:分形树、谢尔宾斯基三角、汉诺塔、迷宫

    定义 递归是一种解决问题的方法,它把一个问题分解为越来越小的子问题,直到问题的规模小到可以被很简单直接解决. 通常为了达到分解问题的效果,递归过程中要引入一个调用自身的函数. 举例 数列求和 def ...

  5. js判断移动端浏览器类型,微信浏览器、支付宝小程序、微信小程序等

    起因 现在市场上各种跨平台开发方案百家争鸣各有千秋,个人认为最成熟的还是hybird方案,简单的说就是写H5各种嵌入,当然作为前端工程师最希望的也就是公司采用hybird方案当作技术路线. 所谓的hy ...

  6. 这样调优之后,单机也能扛下100W连接

    1 模拟单机连接瓶颈 我们知道,通常启动一个服务端会绑定一个端口,例如8000端口,当然客户端连接端口是有限制的,除去最大端口65535和默认的1024端口及以下的端口,就只剩下1 024~65 53 ...

  7. Java:并发笔记-01

    Java:并发笔记-01 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 1. 进程与线程 本章内容 进程和线程的概念 并行和并发的概念 线程基本应用 1.1 ...

  8. Alpha项目展示

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 Alpha-项目展示 我们是谁 删库跑路对不队 我们在做什么 题士 进度如何 进度总览 一.项目与团队亮点 ...

  9. Spring Cloud Gateway 网关限流

    Spring Cloud Gateway 限流 一.背景 二.实现功能 三.网关层限流 1.使用默认的redis来限流 1.引入jar包 2.编写配置文件 3.网关正常响应 4.网关限流响应 2.自定 ...

  10. OSI参考模型(应用层、表示层、会话层、传输层、网络层、数据链路层、物理层)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/104589085 学习课程:<2019王道考研计算机网络> 学习目的 ...