原文链接https://www.lydsy.com/JudgeOnline/problem.php?id=2821

题目传送门 - BZOJ2821

题意

  $n$ 个数,$m$ 组询问,每次问 $[l,r]$ 中有多少个数出现正偶数次。

  $1\leq n,m,a_i\leq 10^5$

题解

  这题的标算是一个分块。但是我不想写分块怎么办?

  bitset 大法好!

  bitset 大法好!

  bitset 大法好!

  发现我们可以每隔 $\sqrt n$ 保存一下前缀序列中每一个数字的出现情况。

  然后询问的时候相当于找到长度 $L-1$ 的前缀序列的数的出现情况和长度 $R$ 的前缀序列的数的出现情况,异或起来,数 0 的个数即可。这个显然可以通过预处理的东西暴力调整,然后手写 bitset 再加一个预处理可以使统计 0 的个数的复杂度也变成 $O(nm/32)$ 。所以总复杂度 $O(nm/32)$ 。这里注意一下调整 $L-1$ 和 $R$ 的 bitset 不能是同一个!。

  然后发现样例萎掉了。

  发现一个数没有出现过不能算进去。

  那怎么办呢?

  补集转化一下:答案变成 “区间不同数值的种数 - 统计异或得到的 bitset 的 1 的个数” 。

  显然“区间不同数值的种数”是可以通过转化成二维数点问题的,直接拖主席树板子。

  然后就 AC 啦。

  时间复杂度 $O(n\log n+n\sqrt n+n^2/32)$ (由于 $n,m,c$ 同阶,所以这里都看作 $n$ )。

代码

#include <bits/stdc++.h>
#define y1 __zzd001
using namespace std;
typedef unsigned uint;
const int N=100405;
int cnt1[65536];
void init(){
for (int i=0;i<65536;i++)
cnt1[i]=cnt1[i>>1]+(i&1);
}
struct BitSet{
uint v[3200];
void clear(){
memset(v,0,sizeof v);
}
uint XOR(int x){v[x>>5]^=1<<(x&31);}
};
int calc(uint v){
return cnt1[v>>16]+cnt1[v&65535];
}
struct Ptree{
static const int S=N*40;
int n;
int root[N],sum[S],ls[S],rs[S],tot;
void build(int &rt,int L,int R){
sum[rt=++tot]=0;
if (L==R)
return;
int mid=(L+R)>>1;
build(ls[rt],L,mid);
build(rs[rt],mid+1,R);
}
void update(int prt,int &rt,int L,int R,int x){
if (!rt||rt==prt)
sum[rt=++tot]=sum[prt];
sum[rt]++;
if (L==R)
return;
if (!ls[rt])
ls[rt]=ls[prt];
if (!rs[rt])
rs[rt]=rs[prt];
int mid=(L+R)>>1;
if (x<=mid)
update(ls[prt],ls[rt],L,mid,x);
else
update(rs[prt],rs[rt],mid+1,R,x);
}
int query(int rt,int L,int R,int xL,int xR){
if (!rt||R<xL||L>xR)
return 0;
if (xL<=L&&R<=xR)
return sum[rt];
int mid=(L+R)>>1;
return query(ls[rt],L,mid,xL,xR)+query(rs[rt],mid+1,R,xL,xR);
}
int Query(int x1,int x2,int y1,int y2){
if (x1>x2||y1>y2)
return 0;
return query(root[x2],0,n,y1,y2)-query(root[x1-1],0,n,y1,y2);
}
void init(int _n){
tot=0;
n=_n;
build(root[0],0,n);
}
void insert(int x,int y){
update(root[x-1],root[x],0,n,y);
}
}pt;
int read(){
int x=0;
char ch=getchar();
while (!isdigit(ch))
ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
}
int n,m,a[N],Pre[N],c;
BitSet v1[330],v2[330];
int main(){
init();
n=read(),c=read(),m=read();
pt.init(n);
memset(Pre,0,sizeof Pre);
for (int i=1;i<=n;i++){
a[i]=read();
pt.insert(i,Pre[a[i]]);
Pre[a[i]]=i;
}
v1[0].clear(),v2[0]=v1[0];
for (int i=1;i*320<=n;i++){
v1[i]=v1[i-1];
for (int j=(i-1)*320+1;j<=i*320;j++)
v1[i].XOR(a[j]);
v2[i]=v1[i];
}
int ans=0;
while (m--){
int L=(read()+ans)%n+1,R=(read()+ans)%n+1;
if (L>R)
swap(L,R);
int all=pt.Query(L,R,0,L-1);
L--;
int l=L/320,r=R/320;
BitSet &sl=v1[l],&sr=v2[r];
l*=320,r*=320;
while (l<L)
sl.XOR(a[++l]);
while (r<R)
sr.XOR(a[++r]);
int tot=0;
for (int i=0;i<3200;i++)
tot+=calc(sl.v[i]^sr.v[i]);
printf("%d\n",ans=all-tot);
int ls=L/320*320,rs=R/320*320;
while (l>ls)
sl.XOR(a[l--]);
while (r>rs)
sr.XOR(a[r--]);
}
return 0;
}

  

BZOJ2821 作诗(Poetize) 主席树 bitset的更多相关文章

  1. BZOJ2821 作诗(Poetize) 【分块】

    BZOJ2821 作诗(Poetize) Description 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好是作诗. 由于时间紧迫,SHY作完诗之后还要虐OI ...

  2. 【分块】BZOJ2821 作诗(Poetize)

    2821: 作诗(Poetize) Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 3265  Solved: 951[Submit][Status][ ...

  3. BZOJ2821 作诗(Poetize) 分块

    题意 算法 经验总结 代码 题意 不带修改,查询数列[1,n]中[l,r]内的出现正偶数次的数的个数, 数列中的数 <= 1e5, n <= 1e5, 强制在线 算法 ​ 查询的内容: 区 ...

  4. bzoj2821: 作诗(Poetize)

    分块 分sqrt(n)块 F[i][j]表示块i到块j的答案 s[i][j]表示数字i在前j块内出现了几次 #include <iostream> #include <cstdio& ...

  5. 2018.09.30 bzoj2821: 作诗(Poetize)(分块)

    传送门 分块经典题目. 先将数列分块. 然后预处理出每两个块之间有多少个数出现了正偶数次. 这样查询的时候对于中间的完整块直接用预处理出的数组搞定. 剩下的暴力枚举求解. 代码: #include&l ...

  6. 2821: 作诗(Poetize)

    2821: 作诗(Poetize) Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1078  Solved: 348[Submit][Status] ...

  7. 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 ...

  8. BZOJ_2821_作诗(Poetize)_分块

    BZOJ_2821_作诗(Poetize)_分块 Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗 之后还要 ...

  9. 【BZOJ2821】作诗(Poetize) 分块

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

随机推荐

  1. Laravel 5.2响应--后台back()->with('提示信息'),前台为什么收不到?

    ### 今天遇到了个小问题,想后台判断数据的时候,返回前台,然后弹窗提示没有数据 但是前台点了有返回,咩有提示信息 ### 网上找了很9⃣️,关于这方面的都是属于验证时候的相关问题,但是我这个跟验证没 ...

  2. 小甜点,RecyclerView 之 ItemDecoration 讲解及高级特性实践

    本篇文章摘自微信公众号 guolin_blog (郭霖)独家发布 毫无疑问,RecyclerView 是现在 Android 世界中最重要的系统组件之一,它的出现就是为了高效代替 ListView 和 ...

  3. EasyUI 如何结合JS导出Excel文件

    出处:http://blog.csdn.net/jumtre/article/details/41119991 EasyUI 如何结合JS导出Excel文件 分类: 技术 Javascript jQu ...

  4. [maven] dependency标签理解

    在maven pom.xml文件中最多的就是dependency标签,我们用maven管理我们项目的依赖.这篇文章简单介绍dependency标签内部各个子标签的意义. 下面是dependency标签 ...

  5. Oracle12c从入门到精通(第二版) PDF 下载

    一:下载地址: 二:本书图样 三本书目录 前言 第一章 Oracle数据库概述 第二章 Oracle在Windows 8上的安装与配置 第三章 SQL基础 第四章 Oracle PL/SQL及编程 第 ...

  6. jquery easyui datagrid 加每页合计和总合计

    jquery easyui datagrid 加每页合计和总合计 一:效果图 二:代码实现 这个只有从后台来处理 后台根据rows 和page两个参数返回的datatable 命名为dt 然后根据dt ...

  7. java.lang.NumberFormatException 错误及解决办法

    package com.geelou.test; public class ErrTest { public static void main(String[] args) { String numS ...

  8. Confluence 6 SQL Server 创建一个数据库和数据库用户

    一旦你成功安装了 SQL Server 服务器,请按照下面的方法为你的 Confluence 创建数据库用户和数据库: 使用你的 SQL 管理员权限,创建一个新的数据库(例如 confluence). ...

  9. Mesh无线网络的定义与WiFi的区别

    Mesh无线网络的定义与WiFi的区别 无线Mesh网络(无线网状网络)也称为「多跳(multi-hop)」网络,它是一种与传统无线网络完全不同的新型无线网络技术.无线网状网是一种基于多跳路由,对等网 ...

  10. vue中 裁剪,预览,上传图片 的插件

    参考地址: https://github.com/dai-siki/vue-image-crop-upload