用离线树状数组维护区间历史值(广义扫描线思想入门)

例题:Codeforces 220B-Little Elephant and Array

涛巨的题解

题目大意:

题意:
给出一个长度为n的数组,有m个询问,每次询问给出一个区间,问这个区间内有多少个数x恰好出现x次

这种题的特点:

1、m次查询,可以离线处理。

一般以各查询区间的右端点排序,用扫描线在相关函数(区间历史值,差分序列)做修改。

2、运用差分序列。一般右端点固定,考虑之前区间,再右边的区间不影响,等到右端点移动时,再修改这个区间的信息。

3、由于扫描线,修改的值往往在要改的地方(及左右两个位置),属于单点修改,树状数组最快。

这题维护的特殊的差分序列 t [maxn] 数组画个表既可以表示。

在这里插入图片描述
相应修改对应下面代码

add(v[a[i]][len-a[i]],1);
if(len>a[i])	add(v[a[i]][len-a[i]-1],-2);
if(len>a[i]+1)	add(v[a[i]][len-a[i]-2],1);

代码:

ll n,m,a[maxn],t[maxn],ans[maxn];
typedef pair<int,int>p;
vector<p>e[maxn];
ll lowbit(int x){
   	return x&(-x);	}
void add(int i,ll v){
   	for(;i<=n;i+=lowbit(i))	t[i]+=v;	}
ll ask(int i){
   
	ll ans=0;
	for(;i;i-=lowbit(i))	ans+=t[i];
	return ans;
}
vector<int>v[maxn];
int main(){
   
	n=read
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值