bzoj 2821 分块
分块:
先预处理,将原序列分成长度为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 分块的更多相关文章
- bzoj 2821 分块处理
大题思路就是分块,将n个数分成sqrt(n)个块,然后 处理出一个w数组,w[i,j]代表第i个块到第j个块的答案 那么对于每组询问l,r如果l,r在同一个块中,直接暴力做就行了 如果不在同一个块中, ...
- BZOJ 2821 分块+二分
题意: N个数,M组询问,每次问[l,r]中有多少个数出现正偶数次. 思路: 把N个数分成sqrt(n)块,预处理d[i][j]表示第i块起点到第j块末尾的答案 枚举起点i,并维护一个数组记录每个数到 ...
- [BZOJ 2821] 作诗(Poetize) 【分块】
题目链接:BZOJ - 2821 题目分析 因为强制在线了,所以无法用莫队..可以使用分块来做. 做法是,将 n 个数分成 n/x 个块,每个块大小为 x .先预处理出 f[i][j] ,表示从第 i ...
- [BZOJ 2821] 作诗
Link: BZOJ 2821 传送门 Solution: 一道类似区间众数的经典分块 由于个数为偶数这样的条件不能支持快速合并 因此要先$O(n*sqrt(n))$预处理出$pre[i][j]$表示 ...
- 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) 分块
Description 有一个长度为n的序列,序列每个元素的范围[1,c],有m个询问x y,表示区间[x,y]中出现正偶数次的数的种类数. Solution 大力分块解决问题. 把序列分块,f[i] ...
- bzoj 2821 作诗 分块
基本思路和蒲公英一样 还是预处理出每两个块间的答案 询问时暴力跑两边的贡献 #include<cstdio> #include<cstring> #include<ios ...
- 【BZOJ 2821】作诗
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=2821 [算法] 如果不强制在线,显然莫队是可以解决此题的,那么,强制在线怎么办呢? ...
- bzoj 2741 分块+可持久化trie
多个询问l,r,求所有子区间异或和中最大是多少 强制在线 做法: 分块+可持久化trie 1.对于每块的左端点i,预处理出i到任意一个j,()i,j)间所有子区间异或和中最大为多少,复杂度O(\(n\ ...
随机推荐
- HDU 2082 找单词 (普通母函数)
题目链接 Problem Description 假设有x1个字母A, x2个字母B,..... x26个字母Z,同时假设字母A的价值为1,字母B的价值为2,..... 字母Z的价值为26.那么,对于 ...
- 如何在移动端app中应用字体图标icon fonts
How to use icon fonts in your mobile apps 在任何APP设计中实现可图形的矢量缩放最完美的方式是使用字体图标. 移动端的设计变的越来越复杂.原因在于多样的屏幕尺 ...
- JS 判断手机操作系统代码
还是利用UA, 返回值: ios, android, unknown function getMobileType () { var ua = window.navigator.userAgent.t ...
- 商城项目(ssm+dubbo+nginx+mysql统合项目)总结(2)
我不会在这里贴代码和详细步骤什么的,我觉得就算我把它贴出来,你们照着步骤做还是会出很多问题,我推荐你们去看一下黑马的这个视频,我个人感觉很不错,一步一步走下来可以学到很多东西.另外,视频和相关文档的话 ...
- 123.Best Time to Buy and Sell Stock III---dp
题目链接:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/description/ 题目大意:与122题类似,只是这 ...
- openjudge-NOI 2.6-1759 最长上升子序列
题目链接:http://noi.openjudge.cn/ch0206/1759/ 题解: 奇怪……之前博客里的o(nlogn)标程在codevs和tyvj上都能AC,偏偏它这里不行 #include ...
- 使用keytool生成ssl密钥文件keystore和truststore
最近在研究Mina的开发,通信的时候需要数据加密,而且mina本身支持SSLFilter过滤器,所以可以采用SSL加密的方式对数据进行加密. 在进行加密之前,我们需要使用keytool(这个存在于C: ...
- AssetBundle——外部加载资源Asset
几篇很不错的文章 AssetBundle创建到使用入门 全面理解Unity加载和内存管理 实用的创建AssetBundle的脚本 相关资源 相关的共享资源下载 本共享包括创建assetbund ...
- fiddler添加监测请求的 ip地址
本文转载自:http://www.jackness.org/2014/12/26/%E7%BB%99fiddler%E6%B7%BB%E5%8A%A0%E7%9B%91%E6%B5%8B%E8%AF% ...
- jquery 修改样式
//显示待办数字 function showdb(url,ID) { jQuery.get(url,function(data,status){ if(!isNaN(data)) { if(da ...