Codeforces 220B - Little Elephant and Array 离线树状数组
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 离线树状数组的更多相关文章
- Educational Codeforces Round 10 D. Nested Segments 离线树状数组 离散化
D. Nested Segments 题目连接: http://www.codeforces.com/contest/652/problem/D Description You are given n ...
- Codeforces 703D Mishka and Interesting sum 离线+树状数组
链接 Codeforces 703D Mishka and Interesting sum 题意 求区间内数字出现次数为偶数的数的异或和 思路 区间内直接异或的话得到的是出现次数为奇数的异或和,要得到 ...
- CodeForces - 220B Little Elephant and Array (莫队+离散化 / 离线树状数组)
题意:N个数,M个查询,求[Li,Ri]区间内出现次数等于其数值大小的数的个数. 分析:用莫队处理离线问题是一种解决方案.但ai的范围可达到1e9,所以需要离散化预处理.每次区间向外扩的更新的过程中, ...
- Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)
http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...
- POJ 3416 Crossing --离线+树状数组
题意: 给一些平面上的点,然后给一些查询(x,y),即以(x,y)为原点建立坐标系,一个人拿走第I,III象限的点,另一个人拿II,IV象限的,点不会在任何一个查询的坐标轴上,问每次两人的点数差为多少 ...
- HDU 2852 KiKi's K-Number(离线+树状数组)
题目链接 省赛训练赛上一题,貌似不难啊.当初,没做出.离线+树状数组+二分. #include <cstdio> #include <cstring> #include < ...
- 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) ,问在每个区间里所有 ...
- 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 ...
- HDU3333 Turing Tree 离线树状数组
题意:统计一段区间内不同的数的和 分析:排序查询区间,离线树状数组 #include <cstdio> #include <cmath> #include <cstrin ...
随机推荐
- iOS8中添加的extensions总结(三)——图片编辑扩展
图片编辑扩展 注:此教程来源于http://www.raywenderlich.com的<iOS8 by Tutorials> 1.准备 与(二)类似的使用Imgur作为图片来源 2. ...
- 你好,C++(13)这道单选题的答案是A、B、C还是D?3.7 枚举类型
3.7 枚举类型 除了之前我们介绍的数值数据和文字数据之外,在现实世界中,常常还会遇到这样一类数据:一道单选题的答案只能是A.B.C.D四个选项中的某一个:红绿灯的颜色只能是红色,绿色和黄色中的某一 ...
- centos的常用命令
公司服务器主要是centos,第一篇就从centos的常用命令开始吧. 转载自:http://www.cnblogs.com/zitsing/archive/2012/05/02/2479009.ht ...
- C# 配置文件读取与修改(转)
C# 配置文件读取与修改 配置文件在很多情况下都使用到, 配置文件分为两种 一种是应用程序的配置文件, 一种是web的配置文件. 两种配置文件最大的区别是web的配置文件更新之后会实时更新, 应用 ...
- CSS样式鼠标点击与经过的效果一样
a:link /* 未访问的链接 */ a:visited /* 已访问的链接 */ a:hover /* 当有鼠标悬停在链接上 */ a:active /* 被选择的链接 */ a,a:visite ...
- TTS异步+同步
微软TTS使用说明 一.SAPI SDK的介绍 SAPI,全称是The Microsoft Speech API.就是微软的语音API.由Windows Speech SDK提供. Windows S ...
- mysql 索引管理原则
最近在学习mysql的索引优化,结合着我们网盟系统的一些业务,翻阅一些资料,整理出如下的一些想法: 1.索引建立的原则一:最左前缀匹配原则 ,非常重要的原则,mysql会一直向右匹配直到遇到范围查询( ...
- jQuery 鼠标拖拽排序
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
- css、js的相互阻塞
先决条件:脚本前面存在外部样式 以下试验虽然是在chrome下,但是对于IE8+以及其他浏览器也适用. 1.内联脚本(http://jsbin.com/mudab/1) <!DOCTYPE ht ...
- Entity Framework with MySQL 学习笔记一(验证标签)
直接上代码 [Table("single_table")] public class SingleTable { [Key] public Int32 id { get; set; ...