题面

之前做过一道很类似的题目 洛谷P4168蒲公英 ,然后看到这题很快就想到了解法,做完这题可以对比一下,真的很像。

题目要求区间内出现次数为正偶数的数字的数量。

数据范围1e5,可以分块。

我们预处理出这么两个数组。

一个是某个数字出现次数的分块前缀和,这个很简单。

一个是sum[ i ][ j ]代表从第i个分块到第j个分块出现次数为正偶数的数字的个数。

这个数组很好维护,只需要枚举左端点分块和右端点分块然后统计数字出现次数即可。

这些代码里有一些细节,可以结合注释理解。

for(int i=1;i<=get_pos(n);i++){
int kin=0;
for(int j=i;j<=get_pos(n);j++){
for(int k=(j-1)*len+1;k<=min(n,j*len);k++){//这里有一些细节
tmp[a[k]]++;
if((tmp[a[k]]&1))//如果这个数加完之后变成了奇数
if(tmp[a[k]]>1)//如果加完之后出现次数大于一,那么这个数就作为正偶数被统计进答案了,要减掉
kin--;
else//否则这个数在加一之前没有被统计过,没有必要更改,这里写个else是因为防止与下面那个else产生冲突
kin+=0;
else//加完之后如果变成了偶数那肯定从奇数变成了正偶数,对答案有贡献
kin++;
}
sum[i][j]=kin;
}
for(int j=1;j<=c;j++)//清空辅助数组
tmp[j]=0; }

接下来处理询问。

对于询问的l,r,算出其所在的分块lb,rb。

若l,r所在分块相同或相邻则暴力计算,时间复杂度n1/2

若l,r所在分块之间相隔至少一个分块,那么先将答案设成这两个分块之间的出现次数为正偶数的数字数量。

然后,计算两边散块内数字对答案的贡献。

情况较多,可结合注释理解。

void get_q(){
ans=0;
for(int i=l;i<=lb*len;i++){
tmp[a[i]]++;
if(tmp[a[i]]&1)//如果这个数在散块中出现次数为奇数
if((tim[rb-1][a[i]]-tim[lb][a[i]])&1)//如果它在中间块中出现次数为奇数,那么它没有被预先统计进答案里,且目前它对答案有贡献
ans++;
else//如果这个数在中间块中出现次数为偶数
if(tim[rb-1][a[i]]-tim[lb][a[i]]>0)//如果这个数在中间块中出现次数为正偶数,那么它已经作为答案被统计过了,现在不符合条件要减掉
ans--;
else//这个数并没有作为答案被统计过
if(tmp[a[i]]>1)//如果这个数在散块中之前已经作为正偶数被统计了,要减掉
ans--;
else//否则并没有影响
ans-=0;
else//这个数在散块中出现次数为偶数
if(tim[rb-1][a[i]]-tim[lb][a[i]]&1)//如果这个数在中间块中出现次数为奇数,那么这个数的出现次数被作为正偶数统计过,要减掉
ans--;
else//否则这个数之前没有算进答案里,要加进去
ans++;
}
for(int i=(rb-1)*len+1;i<=r;i++){//以下分类同上
tmp[a[i]]++;
if(tmp[a[i]]&1)
if((tim[rb-1][a[i]]-tim[lb][a[i]])&1)
ans++;
else
if(tim[rb-1][a[i]]-tim[lb][a[i]]>0)
ans--;
else
if(tmp[a[i]]>1)
ans--;
else
ans-=0;
else
if(tim[rb-1][a[i]]-tim[lb][a[i]]&1)
ans--;
else
ans++;
}
for(int i=l;i<=lb*len;i++)//清空辅助数组
tmp[a[i]]--;
for(int i=(rb-1)*len+1;i<=r;i++)
tmp[a[i]]--;
ans+=sum[lb+1][rb-1];
}

处理单次询问时间复杂度为n1/2,可以通过本题。

#include<bits/stdc++.h>
using namespace std;
const int h=100010;
const int b_h=1010;
int n,m,c;
int len;
int a[h];
int sum[b_h][b_h];
int tim[b_h][h];
int tmp[h];
int get_pos(int x){
return (x-1)/len+1;
}
void get_pre(){
for(int i=1;i<=get_pos(n);i++)
for(int j=1;j<=c;j++)
tim[i][j]+=tim[i-1][j];
for(int i=1;i<=get_pos(n);i++){
int kin=0;
for(int j=i;j<=get_pos(n);j++){
for(int k=(j-1)*len+1;k<=min(n,j*len);k++){
tmp[a[k]]++;
if((tmp[a[k]]&1))
if(tmp[a[k]]>1)
kin--;
else
kin+=0;
else
kin++;
}
sum[i][j]=kin;
}
for(int j=1;j<=c;j++)
tmp[j]=0; }
}
int l,r,lb,rb;
int ans;
void get_vio(){
ans=0;
for(int i=l;i<=r;i++){
tmp[a[i]]++;
if((tmp[a[i]]&1))
if(tmp[a[i]]>1)
ans--;
else
ans+=0;
else
ans++;
}
for(int i=l;i<=r;i++)
tmp[a[i]]--;
}
void get_q(){
ans=0;
for(int i=l;i<=lb*len;i++){
tmp[a[i]]++;
if(tmp[a[i]]&1)
if((tim[rb-1][a[i]]-tim[lb][a[i]])&1)
ans++;
else
if(tim[rb-1][a[i]]-tim[lb][a[i]]>0)
ans--;
else
if(tmp[a[i]]>1)
ans--;
else
ans-=0;
else
if(tim[rb-1][a[i]]-tim[lb][a[i]]&1)
ans--;
else
ans++;
}
for(int i=(rb-1)*len+1;i<=r;i++){
tmp[a[i]]++;
if(tmp[a[i]]&1)
if((tim[rb-1][a[i]]-tim[lb][a[i]])&1)
ans++;
else
if(tim[rb-1][a[i]]-tim[lb][a[i]]>0)
ans--;
else
if(tmp[a[i]]>1)
ans--;
else
ans-=0;
else
if(tim[rb-1][a[i]]-tim[lb][a[i]]&1)
ans--;
else
ans++;
}
for(int i=l;i<=lb*len;i++)
tmp[a[i]]--;
for(int i=(rb-1)*len+1;i<=r;i++)
tmp[a[i]]--;
ans+=sum[lb+1][rb-1];
}
int main(){
scanf("%d%d%d",&n,&c,&m);
len=sqrt(n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),tim[get_pos(i)][a[i]]++;
get_pre();
int lst=0;
for(int i=1;i<=m;i++){
scanf("%d%d",&l,&r);
l=(l+lst)%n+1,r=(r+lst)%n+1;
if(l>r)
swap(l,r);
lb=get_pos(l),rb=get_pos(r);
if(lb>=rb-1)
get_vio();
else
get_q();
lst=ans;
printf("%d\n",ans);
}
return 0;
}

完整代码

洛谷 P4135 作诗 题解的更多相关文章

  1. 洛谷P4135 作诗 (分块)

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

  2. 洛谷P4135 作诗

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

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

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

  4. 洛谷 P4135 作诗

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

  5. 洛谷 P4135 作诗(分块)

    题目链接 题意:\(n\) 个数,每个数都在 \([1,c]\) 中,\(m\) 次询问,每次问在 \([l,r]\) 中有多少个数出现偶数次.强制在线. \(1 \leq n,m,c \leq 10 ...

  6. 洛谷P2832 行路难 分析+题解代码【玄学最短路】

    洛谷P2832 行路难 分析+题解代码[玄学最短路] 题目背景: 小X来到了山区,领略山林之乐.在他乐以忘忧之时,他突然发现,开学迫在眉睫 题目描述: 山区有n座山.山之间有m条羊肠小道,每条连接两座 ...

  7. 【洛谷P3960】列队题解

    [洛谷P3960]列队题解 题目链接 题意: Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n×m ...

  8. 洛谷P2312 解方程题解

    洛谷P2312 解方程题解 题目描述 已知多项式方程: \[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0\] 求这个方程在 \([1,m]\) 内的整数解(\(n\) 和 \(m\) ...

  9. 洛谷P1577 切绳子题解

    洛谷P1577 切绳子题解 题目描述 有N条绳子,它们的长度分别为Li.如果从它们中切割出K条长度相同的 绳子,这K条绳子每条最长能有多长?答案保留到小数点后2位(直接舍掉2为后的小数). 输入输出格 ...

随机推荐

  1. 学习ASP.NET Core Blazor编程系列一——综述

    一.NET 6概述 .NET 6 是微软统一.Net Core与.Net Framework 两大框架的第二个版本,微软在 .NET 5 中开始进行这两大框架的统一之路. .NET 6 将作为长期支持 ...

  2. 一 策略模式 来自CBF4LIFE 的设计模式

    刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,搞到后是周瑜陪了夫人又折兵呀,那咱们先看看这个场景是什么样子的. 先说这个场景中 ...

  3. 如何自动清理 KingbaseES SYS_LOG

    KingbaseES 初始化完成后,默认不会对 sys_log进行清理.如果需要对sys_log进行自动清理,需要设置相关参数. 与日志自动清理有关的参数(默认值)如下: log_filename | ...

  4. git stash总结

    git stash 1. git stash save "message" ​ 执行存储,并添加备注信息(直接git stash 也可以,但没有备注信息) 2. git stash ...

  5. 我的Vue之旅、02 ES6基础、模块、路径、IO

    自定义模块 为什么要模块?模块化源代码能给我们带来什么好处? 试想一个巨无霸网购平台,在没有模块化的情况下,如果出现bug,程序员就要在几百万行代码里调试,导致后期维护成本上升,为了解决问题,模块化按 ...

  6. 使用kuboard部署某一个应用的pod分布于不同的主机上

    情况介绍 1.k8s集群有8个节点,3个节点是master,分别是master1,master2,master3. 5个worker节点,分别是worker1,worke2,worke3,worker ...

  7. Logstash集成GaussDB(高斯DB)数据到Elasticsearch

    GaussDB 简介 GaussDB 数据库分为 GaussDB T 和 GaussDB A,分别面向 OLTP 和 OLAP 的业务用户. GaussDB T 数据库是华为公司全自研的分布式数据库, ...

  8. ingress-nginx自带认证功能【nginx自带】

    问题:通过nginx可以给某些web网站设置登录使用的用户名和密码,现在网站部署到k8s中,通过配置nginx-ingress->service->pod来访问的,怎么给这个网站再配置上访 ...

  9. linux系统排查数据包常用命令

    1.查看当前系统中生效的所有参数 sysctl -a 2.统计处于TIME_WAIT状态的TCP连接数 netstat -ant|grep TIME_WAIT|wc -l 3.统计TCP连接数 net ...

  10. 持续集成指南:GitLab 的 CI/CD 工具配置与使用

    前言 写代码这项工作,本质就是将工作自动化,减少手工操作提供效率,因为人的本质都是懒狗,程序员也不能例外,为了各种意义的效率提升(懒),我们需要持续集成工具,将代码测试.编译.发布这些重复性很高的工作 ...