题面

分析

莫队,往死里卡常,开O2加奇偶性优化可卡过
我才不会告诉你我这道题提交了37次呢

code

// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;i++)
#define anti_loop(i,start,end) for(register int i=start;i>=end;i--)
#define clean(arry,num); memset(arry,num,sizeof(arry));
const int maxn=500000+10,maxm=500000+10;
int n,m,kinds=0;
int vis[10000001+100];
int a[maxn];
int ans[maxn];
int block;
struct node{int l;int r;int q;int bl;}e[maxm];
inline int read()
{int ans=0;char r=getchar();bool neg=false;while(r<'0'||r>'9'){if(r=='-')neg=true;r=getchar();}while(r>='0'&&r<='9'){ans=ans*10+r-'0';r=getchar();}return (neg)?-ans:ans;
}
void write(int x){if(x<0){putchar('-');x=-x;}if(x>9)write(x/10);putchar(x%10+'0');
}
inline bool cmp(node a,node b)
{return (a.bl)^(b.bl)?a.l<b.l:(((a.bl)&1)?a.r<b.r:a.r>b.r);
}
inline void add(int pos)
{if((++vis[a[pos]])==1)++kinds;
}
inline void del(int pos)
{if((--vis[a[pos]])==0)--kinds;
}
int main()
{//freopen("data.txt","r",stdin);n=read();clean(vis,false);//block=sqrt(n);//block=n/sqrt(n*2.0/3);loop(i,1,n)a[i]=read();m=read();loop(i,1,m){e[i].q=i;e[i].l=read();e[i].r=read();e[i].bl=((e[i].l-1)/sqrt(n)/2)+1;}sort(e+1,e+1+m,cmp);int nl=0;int nr=0;loop(i,1,m){int l=e[i].l;int r=e[i].r;while(nl<l)del(nl++);while(nl>l)add(--nl);while(nr>r)del(nr--);while(nr<r)add(++nr);ans[e[i].q]=kinds;}loop(i,1,m){write(ans[i]);printf("\n");}return 0;
}

学到的东西

  • 各种卡常技巧

1.inline和register
2.自增减运算符前置(a++不如写++a)
3.位运算加速
4.快读快输加速(快输用递归居然比数组快!)
5.ios语句对cin,cout的优化(用快读的绕过此处~~)

  • 莫队的各种优化

1.奇偶性优化
莫队玄学奇偶性排序

这个可以帮你每个点平均优化200ms(可怕)

主要操作:把查询区间的排序函数

int cmp(query a, query b) {return belong[a.l] == belong[b.l] ? a.r < b.r : belong[a.l] < belong[b.l];
}

二话不说,直接删掉,换成

int cmp(query a, query b) {return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : ((belong[a.l] & 1) ? a.r < b.r : a.r > b.r);
}

也就是说,对于左端点在同一奇数块的区间,右端点按升序排列,反之降序。
蒟蒻以前一直不懂这个优化是什么原理,所以采用了最笨的方法,画图模拟。。
为什么它的效果这么好?请看下图

最上左边是一组询问,中间是莫队的普通排序,右边是莫队的奇偶性排序

下面两个图分别是对同一组数据莫队的普通排序和奇偶性排序中右指针R随分块序号B的变化规律
从中不难看出,相比起普通排序,奇偶排序的波峰波谷少了将近50%,R指针的位移也少了将近一半
它的主要原理便是右指针跳完奇数块往回跳时在同一个方向能顺路把偶数块跳完,然后跳完这个偶数块又能顺带把下一个奇数块跳完。
由于一般排列中的R在同一block里单调递增,我们可以将R在一个block里的变化看做一座陡峭的山峰,而实际情况下常常有许多山峰,我们将其编号1到n,现在把相邻两座i,i+1(i奇数,i+1偶数)山峰中的i+1座山峰转体180度,和i合在一起(就像上图左下角一样),这样就减少了我们爬过这所有山的难度(实在不行,手画一下图秒懂)

这里有个洛谷某大佬写的较为清晰的cmp函数,可以借鉴,这样子比较不容易出错

inline bool cmp(node a,node b)
{if(a.block==b.block){if(a.block%2==1){return a.r<b.r;}else{return a.r>b.r;}}else{return a.l<b.l;}
}

2.块优化(原创)
一般我们分块时用一个block计算一下块的大小,然后cmp里面就要不断用l来除以block,这样就加大了计算量,不如直接在预处理的时候就把每个节点的block放在结构体里面,这样可以少算一些

//原版
inline bool cmp(node a,node b)
{return (a.l/block)^(b.l/block)?a.l<b.l:(((a.l/block)&1)?a.r<b.r:a.r>b.r);
}
....
int main()
{....block=n/sqrt(n*2.0/3);....loop(i,1,m){e[i].q=i;e[i].l=read();e[i].r=read();}sort(e+1,e+1+m,cmp);
}
//新版
inline bool cmp(node a,node b)
{return (a.bl)^(b.bl)?a.l<b.l:(((a.bl)&1)?a.r<b.r:a.r>b.r);
}
int main()
{....loop(i,1,m){e[i].q=i;e[i].l=read();e[i].r=read();e[i].bl=((e[i].l-1)/sqrt(n)/2)+1;}
....sort(e+1,e+1+m,cmp);return 0;
}

(若有谬误,请及时于下方评论,博主好及时修改)


update 2019年10月15日11:08:24

似乎这道题现在在洛谷上过不了了,数据加强超过了莫队算法的上限.

但是这道题:SP3267 DQUERY - D-query ,是HH的项链的弱化版,是可以用莫队过的

luogu P1972 [SDOI2009] HH的项链【莫队——奇偶优化详解】相关推荐

  1. BZOJ-1878: [SDOI2009]HH的项链(莫队算法)

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 4857  Solved: 2401 [Submit][Sta ...

  2. BZOJ 1878: [SDOI2009]HH的项链 | 莫队

    题解: http://www.lydsy.com/JudgeOnline/problem.php?id=1878 题解: 莫队板子题 核心思想是对区间的询问离线之后按照合理的顺序来优化复杂度 一般的做 ...

  3. P1972 [SDOI2009]HH的项链

    P1972 [SDOI2009]HH的项链 题意: 给你一个序列,问这个序列中的种类数 n,m,ai<=1e6 题解: 三个方法:莫队(会超时),树状数组,主席树(会超时) 莫队就是裸题,不讲了 ...

  4. 【莫队/树上莫队/回滚莫队】原理详解及例题:小B的询问(普通莫队),Count on a tree II(树上莫队),kangaroos(回滚莫队)

    文章目录 问题引入 介绍莫队算法及其实现过程 时间复杂度 莫队算法适用范围 莫队奇偶优化 普通莫队:小B的询问 树上莫队:SP10707 COT2 - Count on a tree II 回滚莫队: ...

  5. P1972 [SDOI2009]HH的项链(离线树状数组)

    整理的算法模板合集: ACM模板 #include<cstdio> #include<algorithm> #include<cstring> #include&l ...

  6. P1972 [SDOI2009] HH的项链

    本质上是区间查询[l,r][l,r][l,r]不重复元素的个数. 考虑离线处理,按rrr升序排序区间.假设当前区间为[l,r][l,r][l,r],我们希望查询中的query(r)−query(l−1 ...

  7. BZOJ 1878: [SDOI2009]HH的项链

    1878: [SDOI2009]HH的项链 Time Limit: 4 Sec  Memory Limit: 64 MB Submit: 3548  Solved: 1757 [Submit][Sta ...

  8. bzoj千题计划181:bzoj1878: [SDOI2009]HH的项链

    http://www.lydsy.com/JudgeOnline/problem.php?id=1878 之前用莫队做的,现在用树状数组 把每种数的第一个出现位置在树状数组中+1 nxt[i] 记录i ...

  9. bzoj1878: [SDOI2009]HH的项链

    树状数组的一类题目 #include<cstdio> #include<cstring> #include<iostream> #include<algori ...

最新文章

  1. 新科技快速指南系列之“量子计算”:历史、现在与未来
  2. [网络安全自学篇] 十八.XSS跨站脚本攻击原理及代码攻防演示(一)
  3. js之数据类型及类型转换
  4. python数据分析与机器学习(Numpy,Pandas,Matplotlib)
  5. 模拟实现string其中的一些知识点
  6. mysql 修改引擎_修改MySQL的数据库引擎为INNODB的方法
  7. bzoj1568 [JSOI2008]Blue Mary开公司 标记永久化线段树
  8. 京东健康CEO辛利军:感谢刘强东的战略格局和超前眼光
  9. php全选删除,php+ajax简单实现全选删除的方法
  10. mobx中跟新了数据视图没变化_如何做一个好的大数据平台架构
  11. 9、两个栈实现队列(Python)
  12. 虚幻4服务端linux,UE4 虚幻4教程 服务端构建后启动错误的解决方法
  13. Word插入图目录,表目录
  14. The Sultan's Successors
  15. 树莓派用网线连接电脑实现上网并开启VNC
  16. OpenCL基础(一)
  17. 使用了 23 的 Java 真的收费了吗?
  18. mt2503 在MMI版本实现AT+CPBF
  19. 在QT中使用MySQL数据库
  20. Android内存优化总结实践

热门文章

  1. 1.ISIS基本理论
  2. pageadmin CMS网站制作教程:栏目单页内容如何修改
  3. oracle设置密码永不过期
  4. C++的STL库常见函数
  5. 基于内容推荐算法html,基于内容的互联网推荐算法
  6. 微博图床php上传,php利用微博当图床
  7. cmake编译时中途报错:undefined reference to ‘xxx‘.未定义引用
  8. 设计模式之代理模式(第二篇)
  9. java就是我的幸福,关于幸福的句子经典
  10. android m是什么版本号,android m是什么 android m是哪个版本