[NOIP2017模拟]count
2017-09-16 22:48
295 查看
题目背景
SOURCE:NOIP2015-SHY-8
题目描述
给定一个元素个数为 n 的整数数组 a 和 Q 个问题,每个问题有 x,y 两个参数,请统计共有多少个整数 K 满足 K 在 a[x]…a[y] 中出现了恰好 K 次。
输入格式
第一行两个整数 n,Q,表示数组 a 的元素个数和询问数;
接下来一行 n 给整数,描述数组 a ;
接下来 Q 行,每行两个数 xi,yi(1≤xi≤yi≤n),表示询问的左右边界。
输出格式
输出 Q 行,每行一个整数表示满足询问的 K 的个数。
样例数据
输入
7 2
3 1 2 2 3 3 7
1 7
3 4
输出
3
1
备注
【样例说明】
Q1: 1、2、3 分别满足,所以共有 3 个数满足要求。
Q2: 2 满足,所以只有 1 个数满足要求。
【数据范围】
对 50% 的输入数据:1≤n,Q≤1000
对 100% 的输入数据:1≤n,Q≤100000,1≤a[i]≤109
分析:这道题用莫队算法,什么是莫队算法呢,就是用前一个询问更新后一个,而这道题要分块,好处是把排序O(n2)降到了O(n√n)。将询问排序,一个询问计算出来之后与下一个询问左右边界比较,然后移动左右边界更新答案。
注意:若前一个询问l(或r)在后一个之外,那么就要从l开始更新;而如果在后一个之内,就要从l之前一个(r之后一个)更新。
代码
本题结。
SOURCE:NOIP2015-SHY-8
题目描述
给定一个元素个数为 n 的整数数组 a 和 Q 个问题,每个问题有 x,y 两个参数,请统计共有多少个整数 K 满足 K 在 a[x]…a[y] 中出现了恰好 K 次。
输入格式
第一行两个整数 n,Q,表示数组 a 的元素个数和询问数;
接下来一行 n 给整数,描述数组 a ;
接下来 Q 行,每行两个数 xi,yi(1≤xi≤yi≤n),表示询问的左右边界。
输出格式
输出 Q 行,每行一个整数表示满足询问的 K 的个数。
样例数据
输入
7 2
3 1 2 2 3 3 7
1 7
3 4
输出
3
1
备注
【样例说明】
Q1: 1、2、3 分别满足,所以共有 3 个数满足要求。
Q2: 2 满足,所以只有 1 个数满足要求。
【数据范围】
对 50% 的输入数据:1≤n,Q≤1000
对 100% 的输入数据:1≤n,Q≤100000,1≤a[i]≤109
分析:这道题用莫队算法,什么是莫队算法呢,就是用前一个询问更新后一个,而这道题要分块,好处是把排序O(n2)降到了O(n√n)。将询问排序,一个询问计算出来之后与下一个询问左右边界比较,然后移动左右边界更新答案。
注意:若前一个询问l(或r)在后一个之外,那么就要从l开始更新;而如果在后一个之内,就要从l之前一个(r之后一个)更新。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> #include<queue> #include<set> using namespace std; int getint() { int sum=0,f=1; char ch; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') { f=-1; ch=getchar(); } for(;ch>='0'&&ch<='9';ch=getchar()) sum=(sum<<3)+(sum<<1)+ch-48; return sum*f; } const int maxn=100010; struct node{ int l,r,id,pos; }q[maxn]; int n,Q,s,res; int a[maxn],c[maxn],ans[maxn]; bool comp(const node &a,const node &b) { if(a.id==b.id) return a.r<b.r; return a.id<b.id; } int main() { freopen("count.in","r",stdin); freopen("count.out","w",stdout); n=getint();Q=getint(); for(int i=1;i<=n;++i) { a[i]=getint(); if(a[i]<=n) c[a[i]]++; } for(int i=1;i<=n;++i) if(c[i]==i) res++; s=(int)sqrt(n); for(int i=1;i<=Q;++i) { q[i].l=getint(),q[i].r=getint(); q[i].id=q[i].l/s+1; q[i].pos=i; } sort(q+1,q+Q+1,comp); int l=1,r=n; for(int i=1;i<=Q;++i) { while(l<q[i].l) { if(a[l]>n) { l++; continue; } if(a[l]==c[a[l]]) res--; if(a[l]==c[a[l]]-1) res++; c[a[l]]--; l++; } while(l>q[i].l)//边界 { l--; if(a[l]>n) continue; if(a[l]==c[a[l]]) res--; if(a[l]==c[a[l]]+1) res++; c[a[l]]++; } while(r>q[i].r) { if(a[r]>n) { r--; continue; } if(a[r]==c[a[r]]) res--; if(a[r]==c[a[r]]-1) res++; c[a[r]]--; r--; } while(r<q[i].r)//边界 { r++; if(a[r]>n) continue; if(a[r]==c[a[r]]) res--; if(a[r]==c[a[r]]+1) res++; c[a[r]]++; } ans[q[i].pos]=res; l=q[i].l,r=q[i].r; } for(int i=1;i<=Q;++i) cout<<ans[i]<<'\n'; return 0; }
本题结。
相关文章推荐
- JZOJ 5395. 【NOIP2017提高A组模拟10.6】Count
- JZOJ 5395. 【NOIP2017提高A组模拟10.6】Count
- 拉格朗日插值法 【NOIP2017提高A组模拟10.6】Count
- [JZOJ5395]【NOIP2017提高A组模拟10.6】Count
- 【JZOJ 5395】【NOIP2017提高A组模拟10.6】Count
- 5230. 【NOIP2017模拟A组模拟8.5】队伍统计
- JZOJ5340. 【NOIP2017模拟9.2A组】春思(2017.9A组)
- JZOJ5249. 【NOIP2017提高A组模拟8.10】文本编辑器
- [JZSC2017]【NOIP2017提高组模拟6.29】总结
- JOZJ5185. 【NOIP2017提高组模拟6.30】tty's sequence
- [NOIP2017模拟]Fibonacci
- 【WinterCamp 2013】楼房重建 && 【NOIP2017提高A组模拟10.8】God Knows
- JZOJ5373. 【NOIP2017提高A组模拟9.17】信仰是为了虚无之人 并查集+启发式合并
- NSFZOJ #6015. 【NOIP2017校内模拟-5】四轮车
- NOIP2017赛前模拟 Game DP (2017.10.30)
- JZOJ100047. 【NOIP2017提高A组模拟7.14】基因变异
- 【jzoj5289】【NOIP2017提高组A组模拟8.17】【偷笑】【数据结构】
- 【jzoj5389】【NOIP2017提高A组模拟9.26】【解梦】
- 【JZOJ5249】【NOIP2017提高A组模拟8.10】文本编辑器
- 【JZOJ4919】【NOIP2017提高组模拟12.10】神炎皇