hdu 5775

题意:给出一个序列,根据冒泡算法,问数字1-N,他能到的最右边和最左边长度。

思路:他能到达的最左边即min(当前在的位置,排序后的位置),最右边即右边有几个比他小的,可用树状数组

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e5+10;
 4 
 5 int t;
 6 int n;
 7 int a[N],f[N];
 8 int l[N],r[N];
 9 
10 void add(int k,int num){
11     while(k<=n){
12         f[k]+=num;
13         k+=k&-k;
14     }
15 }
16 
17 int getsum(int k){
18     int sum=0;
19     while(k){
20         sum+=f[k];
21         k-=k&-k;
22     }
23     return sum;
24 }
25 
26 int main(){
27     scanf("%d",&t);
28     int k=1;
29     while(t--){
30         scanf("%d",&n);
31         int Max=0,Min=1e9+7;
32         memset(f,0,sizeof(f));
33         for(int i=1;i<=n;i++){
34             scanf("%d",&a[i]);
35             Max=max(Max,a[i]);
36             Min=min(Min,a[i]);
37             l[a[i]]=i;
38         }
39         for(int i=n;i>=1;i--){
40             r[a[i]]=i+getsum(a[i])-getsum(Min-1);
41             add(a[i],1);
42         }
43         sort(a+1,a+n+1);
44         for(int i=1;i<=n;i++){
45             l[a[i]]=min(l[a[i]],i);
46         }
47         printf("Case #%d:",k++);
48         for(int i=1;i<=n;i++){
49              //  cout<<l[i]<<" "<<r[i]<<endl;
50             printf(" %d",r[i]-l[i]);
51         }
52         printf("
");
53     }
54 }
原文地址:https://www.cnblogs.com/hhxj/p/7117196.html