BZOJ2821 作诗(Poetize) 主席树 bitset
原文链接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的更多相关文章
- BZOJ2821 作诗(Poetize) 【分块】
BZOJ2821 作诗(Poetize) Description 神犇SJY虐完HEOI之后给傻×LYD出了一题: SHY是T国的公主,平时的一大爱好是作诗. 由于时间紧迫,SHY作完诗之后还要虐OI ...
- 【分块】BZOJ2821 作诗(Poetize)
2821: 作诗(Poetize) Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 3265 Solved: 951[Submit][Status][ ...
- BZOJ2821 作诗(Poetize) 分块
题意 算法 经验总结 代码 题意 不带修改,查询数列[1,n]中[l,r]内的出现正偶数次的数的个数, 数列中的数 <= 1e5, n <= 1e5, 强制在线 算法 查询的内容: 区 ...
- bzoj2821: 作诗(Poetize)
分块 分sqrt(n)块 F[i][j]表示块i到块j的答案 s[i][j]表示数字i在前j块内出现了几次 #include <iostream> #include <cstdio& ...
- 2018.09.30 bzoj2821: 作诗(Poetize)(分块)
传送门 分块经典题目. 先将数列分块. 然后预处理出每两个块之间有多少个数出现了正偶数次. 这样查询的时候对于中间的完整块直接用预处理出的数组搞定. 剩下的暴力枚举求解. 代码: #include&l ...
- 2821: 作诗(Poetize)
2821: 作诗(Poetize) Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 1078 Solved: 348[Submit][Status] ...
- 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 ...
- BZOJ_2821_作诗(Poetize)_分块
BZOJ_2821_作诗(Poetize)_分块 Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗 之后还要 ...
- 【BZOJ2821】作诗(Poetize) 分块
Description 神犇SJY虐完HEOI之后给傻×LYD出了一题:SHY是T国的公主,平时的一大爱好是作诗.由于时间紧迫,SHY作完诗之后还要虐OI,于是SHY找来一篇长度为N的文章,阅读M次, ...
随机推荐
- 【原创】数据库基础之Mysql(3)mysql删除历史binlog
mysql开启binlog后会在/var/lib/mysql下创建binlog文件,如果手工删除,则下次mysql启动会报错: mysqld: File './master-bin.000001' n ...
- SP2-0734: 未知的命令开头 "exp wlc/ra..." - 忽略了剩余的行。
SP2-0734: 未知的命令开头 "exp wlc/ra..." - 忽略了剩余的行. 原来只需要在 $exp wlc/radial_wlc123@ora11g owner=w ...
- Python-数据类型 主键auto_increment
MySQL数据操作: DML========================================================在MySQL管理软件中,可以通过SQL语句中的DML语言来实 ...
- 20)django-session使用
一:目录 1)session原理 2)cookie与session对比 3)session配置 4)session使用 5)示例 二:session原理 Django的Session机制会向请求的浏览 ...
- hive学习02-累加
求出当月的访问次数,截至当月前的每个月最大访问次数.截至当月前每个用户总的访问次数. 数据表如下 A,-, A,-, B,-, A,-, B,-, A,-, A,-, A,-, B,-, B,-, A ...
- css3 曲线阴影,翘边阴影
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 深入理解ajax
http://www.imooc.com/code/13468 基础练习 http://www.imooc.com/video/5644 !ajax! 常用 for ...
- Confluence 6 配置 Web 代理支持
这个页面中的相关平台中的内容是不被支持的.因此,Atlassian 支持不能保证能够为你提供任何支持.请注意,这个页面下面提供的信息仅为你提供参考同时也不能保证所有的的配置能正常工作.如果你按照本页面 ...
- Confluence 6 SQL Server 测试你的数据库连接
在你的数据库设置界面,有一个 测试连接(Test connection)按钮可以检查: Confluence 可以连接你的数据库服务器 数据库字符集和隔离级别是正确的 你的数据库用户有正确的数据库权限 ...
- python并发编程之多线程1
一多线程的概念介绍 threading模块介绍 threading模块和multiprocessing模块在使用层面,有很大的相似性. 二.开启多线程的两种方式 1.创建线程的开销比创建进程的开销小, ...