This problem can be solve in simpler O(NsqrtN) solution, but I will describe O(NlogN) one.

We will solve this problem in offline. For each x (0 ≤ x < n) we
should keep all the queries that end in x. Iterate that x from
0 to n - 1. Also we need to keep some array D such
that for current x Dl + Dl + 1 + ... + Dx will
be the answer for query [l;x]. To keep D correct,
before the processing all queries that end in x, we need to update D.
Let t be the current integer in A,
i. e. Ax,
and vector P be the list of indices of previous occurences of t (0-based
numeration of vector). Then, if |P| ≥ t, you need to add 1 to DP[|P| - t],
because this position is now the first (from right) that contains exactly t occurences
of t. After that, if |P| > t,
you need to subtract 2 from DP[|P| - t - 1],
in order to close current interval and cancel previous. Finally, if |P| > t + 1, then you need additionally add 1 to DP[|P| - t - 2] to
cancel previous close of the interval.

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std; #define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout) const int MAXN = 1e5+100;
int n,m; int a[MAXN],c[MAXN],ans[MAXN];
struct Query
{
int l,r,id;
bool operator < (const Query &t) const {return r<t.r;}
}q[MAXN];
inline int lowbit(int x){return x&(-x);}
void add(int i, int v)
{
while(i<=n)
{
c[i]+=v;
i+=lowbit(i);
}
}
int sum(int x)
{
int ret=0;
while(x>0)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
} int main()
{
int sz;
while(~scanf("%d%d",&n,&m))
{
vector<int>data[MAXN];
CL(c,0);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+1+m);
for(int i=1,k=1;i<=n;i++)
{
if(a[i]<=n)
{
data[a[i]].push_back(i);
sz=data[a[i]].size();
if(sz>=a[i])
{
add(data[a[i]][sz-a[i]],1);
if(sz>a[i])add(data[a[i]][sz-a[i]-1],-2);
if(sz>a[i]+1)add(data[a[i]][sz-a[i]-2],1);
}
}
while(q[k].r==i && k<=m)
{
ans[q[k].id]=sum(q[k].r)-sum(q[k].l-1);
k++;
}
} for(int i=1;i<=m;i++)
printf("%d\n",ans[i]); }
return 0;
}

用于调试理解的及及加了凝视的代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std; #define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout) const int MAXN = 1e5+100;
int n,m; int a[MAXN],c[MAXN],ans[MAXN];
struct Query
{
int l,r,id;
bool operator < (const Query &t) const {return r<t.r;}
}q[MAXN];
inline int lowbit(int x){return x&(-x);}
void add(int i, int v)
{
while(i<=n)
{
c[i]+=v;
i+=lowbit(i);
}
}
int sum(int x)
{
int ret=0;
while(x>0)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
} int main()
{
int sz;
while(~scanf("%d%d",&n,&m))
{
vector<int>data[MAXN];
CL(c,0);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+1+m);
for(int i=1,k=1;i<=n;i++)
{
if(a[i]<=n)
{
data[a[i]].push_back(i);
sz=data[a[i]].size();
if(sz>=a[i])
{
add(data[a[i]][sz-a[i]],1);//从右往左第a[i]次出现a[i]的位置+1
if(sz>a[i])add(data[a[i]][sz-a[i]-1],-2);
//从右往左第a[i]+1次出现a[i]的位置 -2,
//由于当Sz==a[i]的时候,这个位置已经被加过1。此次读到i的时候。
//从右往左第a[i]次出现a[i]的位置也被+1。
//那么查询第a[i]+1次出现a[i]的位置到i。答案就是-2+1+1=0,
//查询第a[i]次出现a[i]的位置到i,答案就是1
if(sz>a[i]+1)add(data[a[i]][sz-a[i]-2],1);
//从右往左第a[i]+2次出现a[i]的位置 +1,之前被+1-2,所以变成0
//这三行代码维护出来,从当前的i往左数,第a[i]次出现a[i]的位置总是1
//第a[i]+1次出现a[i]的位置总是-1,第a[i]+2及很多其它次的位置总是0,这样以i为右端点的区间的查询结果就都对了
}
}
while(q[k].r==i && k<=m)
{
/////////////
printf("#i=%d#\n",i);
for(int j=0;j<=n;j++)
printf("c[%d]=%d\n",j,c[j]);
//////////////
ans[q[k].id]=sum(q[k].r)-sum(q[k].l-1);
k++;
}
} for(int i=1;i<=m;i++)
printf("%d\n",ans[i]); }
return 0;
}

Codeforces 220B - Little Elephant and Array 离线树状数组的更多相关文章

  1. Educational Codeforces Round 10 D. Nested Segments 离线树状数组 离散化

    D. Nested Segments 题目连接: http://www.codeforces.com/contest/652/problem/D Description You are given n ...

  2. Codeforces 703D Mishka and Interesting sum 离线+树状数组

    链接 Codeforces 703D Mishka and Interesting sum 题意 求区间内数字出现次数为偶数的数的异或和 思路 区间内直接异或的话得到的是出现次数为奇数的异或和,要得到 ...

  3. CodeForces - 220B Little Elephant and Array (莫队+离散化 / 离线树状数组)

    题意:N个数,M个查询,求[Li,Ri]区间内出现次数等于其数值大小的数的个数. 分析:用莫队处理离线问题是一种解决方案.但ai的范围可达到1e9,所以需要离散化预处理.每次区间向外扩的更新的过程中, ...

  4. Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)

    http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...

  5. POJ 3416 Crossing --离线+树状数组

    题意: 给一些平面上的点,然后给一些查询(x,y),即以(x,y)为原点建立坐标系,一个人拿走第I,III象限的点,另一个人拿II,IV象限的,点不会在任何一个查询的坐标轴上,问每次两人的点数差为多少 ...

  6. HDU 2852 KiKi's K-Number(离线+树状数组)

    题目链接 省赛训练赛上一题,貌似不难啊.当初,没做出.离线+树状数组+二分. #include <cstdio> #include <cstring> #include < ...

  7. CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组

    题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有 ...

  8. CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组(转)

    转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interestin ...

  9. HDU3333 Turing Tree 离线树状数组

    题意:统计一段区间内不同的数的和 分析:排序查询区间,离线树状数组 #include <cstdio> #include <cmath> #include <cstrin ...

随机推荐

  1. 基于脚本的动画的计时控制(“requestAnimationFrame”)(转)

    requestAnimationFrame 方法的支持,该方法通过在系统准备好绘制动画帧时调用该帧,从而为创建动画网页提供了一种更平滑更高效的方法.在此 API 之前,使用 setTimeout 和  ...

  2. 高放的python学习笔记之基本语法

    python与c++的不同之处 python的语句块不是用{}括起来的而是冒号后面跟一些与比当前语句多一的tab缩进的语句. 1.定义变量 python的变量类型不需要人为指出,会根据赋值的类型决定此 ...

  3. idea intellij 快捷键(ubuntu版本)

    S + C + T 创建测试类 A + F12 开启终端 C + F12 查看类中的方法属性 ----随时更新,记录快捷方式

  4. Ubuntu 10.04启动进入命令行模式

    进终端先  运行 sudo gedit /etc/default/grub  找到 GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash”  改为 GRUB_CMDLINE ...

  5. :after伪类+content内容生成经典应用举例

    一.简单说说content内容生成 content内容生成就是通过content属性生成内容,content属性早在CSS2.1的时候就被引入了,可以使用:before以及:after伪元素生成内容. ...

  6. phplib template说明

    phplib template phplib有五大功能:将数据库驱动和对数据库操作完全分离:支持session:权限许可:模板:购物 车 说明:1.第一个简单的模板页first.html模板中的{ma ...

  7. iscroll.js

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  8. 提高PHP性能的方法技巧

    1.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册 ...

  9. centos 下mysql操作

    MySQL名字的来历MySQL是一个小型关系型数据库管理系统,MySQL被广泛地应用在Internet上的中小型网站中.由于其体积小.速度 快.总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为 ...

  10. Web之CSS开发技巧: CSS @media

    CSS @media 规则非常适合于将 HTML 或 XML 文档定位为目标输出方法.目前,print 媒体的使用非常普遍,与实现单独的 “可打印版本” 相比,print 提供了更加整洁的方式来创建打 ...