HDU-5775 Bubble Sort 树状数组

题目:

P is a permutation of the integers from 1 to N(index starting from 1). 
Here is the code of Bubble Sort in C++. 

for(int i=1;i<=N;++i)
    for(int j=N,t;j>i;--j)
        if(P[j-1]>P[j])
            t=P[j],P[j]=P[j-1],P[j-1]=t;
After the sort, the array is in increasing order. ?? wants to know the absolute values of difference of rightmost place and leftmost place for every number it reached.

有一段长度为N序列,其中元素为1到N(没有重复,顺序是乱的)

在上面这一段冒泡排序后求出每个元素所到达的最右端与最左端的差.

Input

The first line of the input gives the number of test cases T; T test cases follow. 
Each consists of one line with one integer N, followed by another line with a permutation of the integers from 1 to N, inclusive. 

第一行是测试样例数量

每个测试样例第一行是一个整数N,接下来N行是序列中的数.

limits 

T <= 20 
1 <= N <= 100000 
N is larger than 10000 in only one case.

Output

For each test case output “Case #x: y1 y2 … yN” (without quotes), where x is the test case number (starting from 1), and yi is the difference of rightmost place and leftmost place of number i.

对于每一个测试样例输出 Case #x: y1 y2 … yN,y1表示第x个测试样例元素值为1的元素所到达的最右端与最左端的差.

注意:最后一个数没有空格.

Sample Input

2
3
3 1 2
3
1 2 3

Sample Output

Case #1: 1 1 2
Case #2: 0 0 0

Hint

In first case, (3, 1, 2) -> (3, 1, 2) -> (1, 3, 2) -> (1, 2, 3)
the leftmost place and rightmost place of 1 is 1 and 2, 2 is 2 and 3, 3 is 1 and 3
In second case, the array has already in increasing order. So the answer of every number is 0.

在第一个测试样例中,值为1所到达的最左端为1(下标),最右端为2(下标)…….

主要思路

每个元素所到达的最左端即为min(d,i).i为其当前的位置,d为其值的大小.最右端为n-x,x为右边比它大的数的个数.

我们用树状数组维护比它小的数的个数即可.

AC代码:

#include<cstdio>
#include<cstring>
#define lowbit(x) x&-x
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
int C[100005],n,ans[100005];
void Add(int x){
	while(x<=n){
		C[x]++;
		x+=lowbit(x);
	}
}
int sum(int x){
	int res=0;
	while(x){
		res+=C[x];
		x-=lowbit(x);
	}
	return res;
}
int main(){
	int T,cnt=0;
	scanf("%d",&T);
	while(T--){
		memset(C,0,sizeof(C));
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			int d;
			scanf("%d",&d);
			int l=min(d,i);//左端点 
			int r=d+(i-1-sum(d));//右端点 这条式子可以自己推一下. 
			ans[d]=r-l;
			Add(d);
		}
		printf("Case #%d: ",++cnt);
		for(int i=1;i<n;i++)printf("%d ",ans[i]);
		printf("%d\n",ans[n]);
	}
}

猜你喜欢

转载自blog.csdn.net/qq_35320178/article/details/81094011
今日推荐