树状数组-例题

Posted wolfbeyond

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组-例题相关的知识,希望对你有一定的参考价值。

例题1 cows


 

题目描述:

Farmer John‘s cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in his field is particularly good.

Farmer John has N cows (we number the cows from 1 to N). Each of Farmer John‘s N cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval [S,E].

But some cows are strong and some are weak. Given two cows: cow i and cow j, their favourite clover range is [Si, Ei] and [Sj, Ej]. If Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj, we say that cow i is stronger than cow j.

For each cow, how many cows are stronger than her? Farmer John needs your help!

输入

The input contains multiple test cases.
For each test case, the first line is an integer N (1 <= N <= 10 5), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 10 5) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge.

The end of the input contains a single 0.

输出

The input contains multiple test cases.
For each test case, the first line is an integer N (1 <= N <= 10 5), which is the number of cows. Then come N lines, the i-th of which contains two integers: S and E(0 <= S < E <= 10 5) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge.

The end of the input contains a single 0.

样例输入

 

3
1 2
0 3
3 4
0

 

样例输出

 

1 0 0

 

提示

Huge input and output,scanf and printf is recommended.

 


 

题目意思:

给定n各区间,为S1-Sn和E1-En

对于每一个区间[Si,Ei]求出能够覆盖自身的区间的数量

题目思路:

使用树状数组,排序cow(表示每个区间)数组,按E从大到小排序,那么如果E相等,则排序S从小到大排。

那么排序之后的结果cow就保证能覆盖[i,j]这个区间的区间在cow[i]之前。

样例实现:

此处只演示较为复杂的排序部分。

  1. 输入[1 2][0 3][3 4]
  2. 先排序
  3. 排序完后为[3,4][1,2][0,3]
  4. 那么此时能覆盖[1,2]的个数为1,[0,3]的个数为0(不符合S>S),[3,4]的个数为0
  5. 输出1,0,0

此演示省略了判断与查询、更新的部分,请谅解。

源码

 

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

int cas=1,T;
int cnt[100100];
int ans[100010];

struct node{
	int s,e,index;
}cow[100010];

int n;
int lowbit(int x){
	return x&(-x);
}
int sum(int x){
	int ans=0;
	while(x>0){
		ans+=cnt[x];
		x-=lowbit(x);
	}
	return ans;
}
void add(int x,int v){
	while (x<=100010){
		cnt[x]+=v;
		x+=lowbit(x);
	}
}
bool cmp(node a,node b){
    if(a.e!=b.e)
	    return a.e>b.e;
    return a.s<b.s;
}

int main(){
	while(scanf("%d",&n)!=EOF && n){
		memset(ans,0,sizeof(ans));
		memset(cnt,0,sizeof(cnt));
		for(int i=0;i<n;i++){
			scanf("%d%d",&cow[i].s,&cow[i].e);
			cow[i].s++;
			cow[i].e++;
			cow[i].index=i;
		}
		sort(cow,cow+n,cmp);
	    ans[cow[0].index]=sum(cow[0].s);
		add(cow[0].s,1);
		for(int i=1;i<n;i++){
			if (cow[i].s==cow[i-1].s && cow[i].e==cow[i-1].e)
				ans[cow[i].index]=ans[cow[i-1].index];
			else
				ans[cow[i].index]=sum(cow[i].s);
			add(cow[i].s,1);
		}
		for (int i=0;i<n-1;i++)
			printf("%d ",ans[i]);
		printf("%d
",ans[n-1]);
	}
	return 0;
}

 















以上是关于树状数组-例题的主要内容,如果未能解决你的问题,请参考以下文章

树状数组求区间和例题练习(Java实现)

luoguP3374ybtoj树状数组例题1单点修改区间查询

ybtoj树状数组差分例题4区间修改区间查询

浅析树状数组

树状数组模板1(例题洛谷P3374)(单点修改+区间查询)

luoguP1908ybtoj树状数组例题2逆序对