分块:

先预处理,将原序列分成长度为len的许多块,计算从第i块到第j块的答案,(可以做到O(n*n/len))。

每次询问时,将询问的区间分成三部分,:左边,中间,右边,中间是尽量大的一个块区间,其答案已经计算得到,左右两边加起来最多有2*len个元素,暴力计算其对答案的影响。O(q*len*f(n)),f(n)是暴力加入一个元素的代价。

这道题f(n)是log(n)

总的复杂度:f(n) = O( n*n/len + q*len*log(n) ),

当len = n*(q*log(n))-1/2时取最小值.

 /**************************************************************
Problem: 2821
User: idy002
Language: C++
Result: Accepted
Time:24352 ms
Memory:13728 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define maxn 100010
#define maxs 1510
#define isok(a) ((a)>0&&!((a)&1))
using namespace std; int n, c, m;
int a[maxn], f[maxs][maxs];
int lx[maxn], rx[maxn], mno[maxn], stot;
int cnt[maxn], cur_ans;
int vs[maxn], vt[maxn], vp[maxn];
bool met[maxn]; struct Pair {
int w, pos;
Pair(){}
Pair( int w, int pos ) : w(w), pos(pos) {}
};
Pair vod[maxn];
bool cmpwp( const Pair & a, const Pair & b ) {
return a.w<b.w || (a.w==b.w && a.pos<b.pos);
}
bool cmpp( const Pair & a, const Pair & b ) {
return a.pos<b.pos;
} void part() {
int len = (int)(double)sqrt((double)n/(log((double)n)/log()))+;
stot = n/len + (n%len!=);
for( int i=; i<=stot; i++ ) {
lx[i] = rx[i-]+;
rx[i] = rx[i-]+len;
if( i==stot ) rx[i] = n;
for( int j=lx[i]; j<=rx[i]; j++ )
mno[j] = i;
}
}
inline void update( int oldv, int newv ) {
bool od, nw;
od = isok(oldv);
nw = isok(newv);
if( od && !nw ) cur_ans--;
else if( !od && nw ) cur_ans++;
} void prep() {
for( int i=; i<=n; i++ )
vod[i] = Pair(a[i],i);
sort( vod+, vod++n, cmpwp );
for( int i=; i<=n; i++ ) {
if( vod[i].w!=vod[i-].w )
vs[vod[i].w] = vt[vod[i-].w] = i;
}
vt[vod[n].w] = n+;
for( int i=; i<=n; i++ ) vp[i] = vod[i].pos; for( int i=; i<=stot; i++ ) {
for( int j=i; j<=stot; j++ ) {
for( int k=lx[j]; k<=rx[j]; k++ ) {
update( cnt[a[k]], cnt[a[k]]+ );
cnt[a[k]]++;
}
f[i][j] = cur_ans;
}
cur_ans = ;
memset( cnt, , sizeof(cnt) );
}
} int qu_cnt( int w, int l, int r ) {
return upper_bound( vp+vs[w], vp+vt[w], r )
- lower_bound( vp+vs[w], vp+vt[w], l );
}
int query( int l, int r ) {
int ml=mno[l], mr=mno[r];
int rt;
if( ml==mr ) {
for( int j=l; j<=r; j++ ) {
update( cnt[a[j]], cnt[a[j]]+ );
cnt[a[j]]+=;
}
rt = cur_ans;
cur_ans = ;
for( int j=l; j<=r; j++ )
cnt[a[j]]--;
return rt;
}
if( mno[l]==mno[l-] ) ml++;
if( mno[r]==mno[r+] ) mr--;
cur_ans = f[ml][mr];
for( int j=l; j<lx[ml]; j++ ) {
if( met[a[j]] ) continue;
met[a[j]] = true;
int t1 = qu_cnt(a[j],l,r);
int t2 = qu_cnt(a[j],lx[ml],rx[mr]);
update( t2, t1 );
}
for( int j=r; j>rx[mr]; j-- ) {
if( met[a[j]] ) continue;
met[a[j]] = true;
int t1 = qu_cnt(a[j],l,r);
int t2 = qu_cnt(a[j],lx[ml],rx[mr]);
update( t2, t1 );
}
rt = cur_ans; cur_ans = ;
for( int j=l; j<lx[ml]; j++ ) met[a[j]]=false;
for( int j=r; j>rx[mr]; j-- ) met[a[j]]=false;
return rt;
} int main() {
scanf( "%d%d%d", &n, &c, &m );
for( int i=; i<=n; i++ ) scanf( "%d", a+i );
part();
prep();
for( int i=,x=,l,r; i<=m; i++ ) {
scanf( "%d%d", &l, &r );
l = (l+x)%n+;
r = (r+x)%n+;
if( l>r ) swap(l,r);
printf( "%d\n", x=query(l,r) );
}
}

bzoj 2821 分块的更多相关文章

  1. bzoj 2821 分块处理

    大题思路就是分块,将n个数分成sqrt(n)个块,然后 处理出一个w数组,w[i,j]代表第i个块到第j个块的答案 那么对于每组询问l,r如果l,r在同一个块中,直接暴力做就行了 如果不在同一个块中, ...

  2. BZOJ 2821 分块+二分

    题意: N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次. 思路: 把N个数分成sqrt(n)块,预处理d[i][j]表示第i块起点到第j块末尾的答案 枚举起点i,并维护一个数组记录每个数到 ...

  3. [BZOJ 2821] 作诗(Poetize) 【分块】

    题目链接:BZOJ - 2821 题目分析 因为强制在线了,所以无法用莫队..可以使用分块来做. 做法是,将 n 个数分成 n/x 个块,每个块大小为 x .先预处理出 f[i][j] ,表示从第 i ...

  4. [BZOJ 2821] 作诗

    Link: BZOJ 2821 传送门 Solution: 一道类似区间众数的经典分块 由于个数为偶数这样的条件不能支持快速合并 因此要先$O(n*sqrt(n))$预处理出$pre[i][j]$表示 ...

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

  6. BZOJ 2821作诗(Poetize) 分块

    Description 有一个长度为n的序列,序列每个元素的范围[1,c],有m个询问x y,表示区间[x,y]中出现正偶数次的数的种类数. Solution 大力分块解决问题. 把序列分块,f[i] ...

  7. bzoj 2821 作诗 分块

    基本思路和蒲公英一样 还是预处理出每两个块间的答案 询问时暴力跑两边的贡献 #include<cstdio> #include<cstring> #include<ios ...

  8. 【BZOJ 2821】作诗

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2821 [算法] 如果不强制在线,显然莫队是可以解决此题的,那么,强制在线怎么办呢? ...

  9. bzoj 2741 分块+可持久化trie

    多个询问l,r,求所有子区间异或和中最大是多少 强制在线 做法: 分块+可持久化trie 1.对于每块的左端点i,预处理出i到任意一个j,()i,j)间所有子区间异或和中最大为多少,复杂度O(\(n\ ...

随机推荐

  1. 【译】第四篇 SQL Server代理配置数据库邮件

    本篇文章是SQL Server代理系列的第四篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.SQL Serve ...

  2. escapeRegExp捕捉通配符的代码解析

    费了好几个小时,把一小段正则代码搞通了,回顾并记下,加深记忆. 该段代码来自yii.js,它也是引自stackoverflow,地址是:http://stackoverflow.com/questio ...

  3. F - Warm up HDU - 4612 tarjan缩点 + 树的直径 + 对tajan的再次理解

    题目链接:https://vjudge.net/contest/67418#problem/F 题目大意:给你一个图,让你加一条边,使得原图中的桥尽可能的小.(谢谢梁学长的帮忙) 我对重边,tarja ...

  4. WordPress浏览数插件的安装使用

    插件安装很容易,但是和大多插件都一样,安装后需要调用代码才能显示,我安装后,也调用了.但是就是不显示,后来才发现,我从其他地方复制过来的代码,函数是中文的单引号,这样致使函数失效,注意代码中参数的引号 ...

  5. VueJS $refs 在 ElementUI 中遇到的问题

    表单验证的时候  $refs 拿不到 暂且是用 $nextTick 解决,具体原因有待研究 假入在 created 中注册时间来验证 validate,那就放在mounted中 或者...注册了 ev ...

  6. DAY1-GO初识(概述)

    一.概述 1.特征 1.1.语法简单:规则严谨.保留指针.但默认阻止指针运算.将切片和字典作为内置类型.更好的维护性: 1.2.并发模型:运行时用GOroutine,一个关键字.简单而自然:搭配cha ...

  7. Linux实用命令之xdg-open

    为什么要介绍 xdg-open 呢,得先从需求说起. 一般在控制台中,可以使用命令操作各式文本文件.但难以避免,需要操作一些非文本文件,如 pdf,doc 等. 此时,一般的做法是,打开文件管理器,再 ...

  8. host与guest间共享文件夹的三种方法(原创)

    一,用samba实现host与guest共享文件 Samba简介:SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算 ...

  9. Android检测富文本中的<img标签并实现点击效果

    本文旨在:通过点击一张图片Toast输出位置与url链接. 闲话少说,实现原理大概是酱紫的::通过正则表达式检测富文本内的图片集合并获取url,在src=“xxx” 后面添加 onclick方法,至于 ...

  10. java版云笔记(五)

    下来是创建笔记本,创建笔记,这个没什么难点和前面是一样的. 创建笔记本 首先点击"+"弹出添加笔记的对话框,然后点击确定按钮创建笔记本. //点击"+"弹出添加 ...