CodeForces - 220B Little Elephant and Array (莫队+离散化 / 离线树状数组)
题意:N个数,M个查询,求[Li,Ri]区间内出现次数等于其数值大小的数的个数。
分析:用莫队处理离线问题是一种解决方案。但ai的范围可达到1e9,所以需要离散化预处理。每次区间向外扩的更新的过程中,检查该位置的数ai的出现次数是否已经达到ai或ai+1,以判断是否要更新结果。同理,区间收缩的时候判断ai出现次数是否达到ai或ai-1。
另一种更高效的方法是使用树状数组离线处理查询。用一个vector数组维护每个ai以此出现的位置。显然ai>N的数不会对结果做出贡献,所以数组开1e5就足够了。树状数组的维护操作:从1道N递推,当ai的出现次数sz>=ai后,对其从右往左数的第ai次出现的位置+1;当出现次数sz>ai次后,需要对从右往左数第ai+1的位置减2;但是出现次数sz>ai+1次后,上述操作会多减去一部分,那么相应的就应该在从右往左数第ai+2次出现的位置上+1。
莫队代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
const int maxn=1e5+;
typedef long long LL;
int N,M,res;
struct Node{
int val;
int id;
bool operator < (const Node &p) const {return val<p.val;}
}a[maxn];
bool cmpid(const Node &x,const Node &y) {return x.id<y.id;} int b[maxn];
int pos[maxn],cnt[maxn],block; //块数
int ans[maxn];
int v[maxn]; //离散化
struct Query{
int L,R,id;
}Q[maxn];
bool cmp1(const Query& x,const Query& y){ //根据所属块的大小排序
if(pos[x.L]==pos[y.L]) return x.R<y.R;
return pos[x.L]<pos[y.L];
} void add(int pos)
{
int id = v[a[pos].id];
if(cnt[id]==b[pos]-) res++;
else if(cnt[id]==b[pos]) res--;
cnt[id]++;
} void pop(int pos)
{
int id = v[a[pos].id];
if(cnt[id]==b[pos]) res--;
else if(cnt[id]==b[pos]+) res++;
cnt[id]--;
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
int cas=;
while(scanf("%d%d",&N,&M)==){
block = ceil(sqrt(1.0*N));
memset(cnt,,sizeof(cnt));
for(int i=;i<=N;++i){
scanf("%d",&a[i].val);
a[i].id = i;
b[i] = a[i].val;
pos[i]=i/block;
}
//离散化
sort(a+,a+N+);
int tag = ;
v[a[].id] = tag;
for(int i=;i<=N;++i){
if(a[i].val == a[i-].val) v[a[i].id] = tag;
else v[a[i].id] = ++tag;
}
sort(a+,a+N+,cmpid); for(int i=;i<=M;++i){
scanf("%d%d",&Q[i].L,&Q[i].R);
Q[i].id = i;
}
sort(Q+,Q+M+,cmp1);
res=;
int curL=,curR=;
for(int i=;i<=M;++i){
while(curL>Q[i].L) add(--curL);
while(curR<Q[i].R) add(++curR);
while(curL<Q[i].L) pop(curL++);
while(curR>Q[i].R) pop(curR--);
ans[Q[i].id] = res;
}
for(int i=;i<=M;++i)
printf("%d\n",ans[i]);
}
return ;
}
离线树状数组代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
using namespace std;
const int maxn=1e5+;
typedef long long LL;
int N,M;
int a[maxn];
int ans[maxn];
struct Query{
int L,R,id;
bool operator < (const Query &q) const {return R<q.R;}
}Q[maxn]; int bit[maxn];
inline int lowbit(int x) {return x&(-x);} void add(int i,int val){
for(;i<=N;i+=lowbit(i)) bit[i]+=val;
} int sum(int i){
int res=;
for(;i>;i-=lowbit(i)) res+=bit[i];
return res;
} #define LOCAL
int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T;
int cas=;
while(scanf("%d%d",&N,&M)==){
vector<int> pos[maxn];
memset(bit,,sizeof(bit));
for(int i=;i<=N;++i){
scanf("%d",&a[i]);
} for(int i=;i<=M;++i){
scanf("%d%d",&Q[i].L,&Q[i].R);
Q[i].id = i;
}
sort(Q+,Q+M+); int la=;
for(int i=;i<=N;++i){
if(a[i]<=N){ //如果a[i]>N 那么不可能对结果有贡献
pos[a[i]].push_back(i); //记录出现的位置
int sz = pos[a[i]].size();
if(sz>=a[i]){
add(pos[a[i]][sz-a[i]],); //对从右往左数的第a[i]次出现的位置,加1
//若a[i]出现的次数大于a[i],从右往左数出现的第a[i]+1次的位置已经被加1,不能作出贡献的前缀被多加了2,所以减去2
if(sz>a[i]) add(pos[a[i]][sz-a[i]-],-);
//但是若a[i]出现的次数大于a[i]+1,那么之前的-2操作就需要“补偿回来”
if(sz>a[i]+) add(pos[a[i]][sz-a[i]-],);
}
}
while(la<=M && Q[la].R==i){
ans[Q[la].id] = sum(Q[la].R) - sum(Q[la].L-);
la++;
}
if(la>M) break;
}
for(int i=;i<=M;++i)
printf("%d\n",ans[i]);
}
return ;
}
CodeForces - 220B Little Elephant and Array (莫队+离散化 / 离线树状数组)的更多相关文章
- codeforces 220B . Little Elephant and Array 莫队+离散化
传送门:https://codeforces.com/problemset/problem/220/B 题意: 给你n个数,m次询问,每次询问问你在区间l,r内有多少个数满足其值为其出现的次数 题解: ...
- CodeForces - 375D Tree and Queries (莫队+dfs序+树状数组)
You have a rooted tree consisting of n vertices. Each vertex of the tree has some color. We will ass ...
- 【序列莫队+二分答案+树状数组】POJ2104-K-th Number
[题目大意] 给出一个长度为n的序列和m组查询(i,j,k),输出[i,j]中的第k大数. [思路] 先离散化然后莫队分块.用树状数组来维护当前每个值的个数,然后对于每次询问二分答案即可. 又一次实力 ...
- SPOJ DQUERY - D-query (莫队算法|主席树|离线树状数组)
DQUERY - D-query Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query ...
- Educational Codeforces Round 10 D. Nested Segments 离线树状数组 离散化
D. Nested Segments 题目连接: http://www.codeforces.com/contest/652/problem/D Description You are given n ...
- Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)
http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...
- Codeforces Round #510 (Div. 2) D. Petya and Array(离散化+反向树状数组)
http://codeforces.com/contest/1042/problem/D 题意 给一个数组n个元素,求有多少个连续的子序列的和<t (1<=n<=200000,abs ...
- Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum (离线树状数组+前缀xor)
题目链接:http://codeforces.com/contest/703/problem/D 给你n个数,m次查询,每次查询问你l到r之间出现偶数次的数字xor和是多少. 我们可以先预处理前缀和X ...
- Codeforces Round #229 (Div. 2) C. Inna and Candy Boxes 树状数组s
C. Inna and Candy Boxes Inna loves sweets very much. She has n closed present boxes lines up in a ...
随机推荐
- nodejs操作图片方法
最近项目中用到nodejs做图片服务器,用户上传图片生成缩略图返回地址一系列操作. 原来一直用.net平台,所有都封装好了生成缩略图这种分分钟就解决了,遂度娘一番全是调用imagemagick和gra ...
- Visual Studio 2012/2010/2008 远程调试
第一步:将你本地的账号密码设置成跟服务器一样,因为远程调试也是需要用户凭证的. 第二步:将vs工具里的Remote Debugger文件夹拷贝到目标机器.大致的目录应该是:D:\Program Fil ...
- 多媒体开发之rtsp 打包发流---rtsp发送
http://blog.csdn.net/ttxk/article/details/5279889 http://www.cnblogs.com/haibindev/p/3434922.html rt ...
- C语言中文网
网址:http://c.biancheng.net/cpp/ 涵盖如下:
- 如何在ChemDraw 15.1 Pro中添加模板
ChemDraw化学绘图工具为了方便用户的使用,特地开发了众多的各种类型模板.用户在绘制一些简单或复杂的化学结构式时,可以直接从ChemDraw模板库里直接调用使用,虽然ChemDraw模板非常的丰富 ...
- WPF DataGrid 获取选中的当前行某列值
方法一: DataRowView mySelectedElement = (DataRowView)dataGrid1.SelectedItem; ]ToString(); 方法二: var a = ...
- SurvivalShooter学习笔记(七.玩家射击)
玩家射击:(这个脚本放在玩家的空子物体上,这个位置为枪口位置) 点击鼠标,玩家射击: 射击枪口发光,射击通过射线,方向有激光效果:(关于射线不明白可以参考Unity射线相关) 射击有射击音效 射击有每 ...
- C# 多线程学习(五)线程同步和冲突解决
from:https://blog.csdn.net/codedoctor/article/details/74358257 首先先说一个线程不同步的例子吧,以下为售票员的模拟售票,多个售票员出售10 ...
- 巨蟒python全栈开发-第24天 内置常用模块3
一. 1.re模块基础知识 2.python模块&re正则模块 3.实战:re模块&python(链家&电影天堂&豆瓣) 复习:上节课重点(1)sys.path 模块的 ...
- 指定文件夹 指定文件后缀名 删除整个文件夹 git 冲突解决 create a new repository on the command line push an existing repository from the command line
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001375840038939c2 ...