莫队算法小总结 x
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了莫队算法小总结 x相关的知识,希望对你有一定的参考价值。
-
- 693通过
- 1.5K提交
- 题目提供者 lych
- 标签 各省省选 2009山东 云端
- 难度 提高+/省选-
- 时空限制 1s / 128MB
题目背景
无
题目描述
HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义。
HH 不断地收集新的贝壳,因此,他的项链变得越来越长。
有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了。
于是,他只好求助睿智的你,来解决这个问题。
输入输出格式
输入格式:第一行:一个整数N,表示项链的长度。
第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间的整数)。
第三行:一个整数M,表示HH 询问的个数。
接下来M 行:每行两个整数,L 和R(1 ≤ L ≤ R ≤ N),表示询问的区间。
输出格式:M 行,每行一个整数,依次表示询问对应的答案。
输入输出样例
6 1 2 3 4 3 5 3 1 2 3 5 2 6
2 2 4
说明
数据范围:
对于100%的数据,N <= 50000,M <= 200000。
思路o_O:
1)莫队
2)离线+树状数组(然而我并不会(?¯∀¯?))
上代码╰( ̄▽ ̄)╮:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #define LL long long using namespace std; const int N = 50010; const int M = 200010; int n,m,k,curL,curR; int answer; int a[N]; LL cnt[M],ans[M]; struct G { int l,r,id,block; bool operator < (const G &qwq)const { if(block==qwq.block) return r < qwq.r; else return block < qwq.block; } }t[M]; void add(int pre) { if(++cnt[a[pre]] == 1) answer++; } void change(int pre) { if(--cnt[a[pre]] == 0) answer--; } void modui() { sort(t+1,t+m+1); curL=1,curR=0; for(int i=1;i<=m;i++) { int L=t[i].l,R=t[i].r; while(curL<L) change(curL++); while(curL>L) add(--curL); while(curR<R) add(++curR); while(curR>R) change(curR--); ans[t[i].id]=answer; } } int main() { scanf("%d",&n); int size=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); scanf("%d",&m); for(int i=1,l,r;i<=m;i++) { scanf("%d%d",&t[i].l,&t[i].r); t[i].id=i; t[i].block=(t[i].l-1)/size+1; } modui(); for(int i=1;i<=m;i++) printf("%d\\n",ans[i]); return 0; }
-
- 157通过
- 244提交
- 题目提供者 BDF1
- 标签 云端↑
- 难度 提高+/省选-
- 时空限制 1s / 128MB
题目描述
小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求(Sigma)∑(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。
小B请你帮助他回答询问。
输入输出格式
输入格式:第一行,三个整数N、M、K。
第二行,N个整数,表示小B的序列。
接下来的M行,每行两个整数L、R。
输出格式:M行,每行一个整数,其中第i行的整数表示第i个询问的答案。
输入输出样例
6 4 3 1 3 2 1 1 3 1 4 2 6 3 5 5 6
6 9 5 2
说明
对于全部的数据,1<=N、M、K<=50000
思路O(∩_∩)O~~:
裸的莫队题...只是可惜我是真的没搞明白为什么可以这样做...然后胡乱敲了一个模板,啪的一下就AC了....
坑点╭(╯^╰)╮:
看样子好像并没有使用到k...
上代码{>~<}:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #define LL long long using namespace std; const int N = 50010; int n,m,k,curL,curR; int answer; int a[N]; LL cnt[N],ans[N]; struct G { int l,r,num,block; bool operator < (const G &qwq)const { if(block==qwq.block) return r < qwq.r; else return block < qwq.block; } }t[N]; void change(int pre,bool flag) { if(flag) answer-=(--cnt[a[pre]])<<1|1; else answer+=(cnt[a[pre]]++)<<1|1; } void modui() { sort(t+1,t+m+1); curL=1,curR=0; for(int i=1;i<=m;i++) { int L=t[i].l,R=t[i].r; while(curL<L) change(curL++,1); while(curL>L) change(--curL,0); while(curR<R) change(++curR,0); while(curR>R) change(curR--,1); ans[t[i].num]=answer; } } int main() { scanf("%d%d%d",&n,&m,&k); int size=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1,l,r;i<=m;i++) { scanf("%d%d",&t[i].l,&t[i].r); t[i].num=i; t[i].block=(t[i].l-1)/size+1; } modui(); for(int i=1;i<=m;i++) printf("%lld\\n",ans[i]); return 0; }
(___r___)
参考博客:
1.http://foreseeable97.logdown.com/posts/158522-233333
2.http://www.cnblogs.com/hzf-sbit/p/4056874.html
3.http://ydcydcy1.blog.163.com/blog/static/21608904020134411543898/
4.http://vawait.com/manhattanmst/
5.http://blog.csdn.net/huzecong/article/details/8576908
以上是关于莫队算法小总结 x的主要内容,如果未能解决你的问题,请参考以下文章