题意:给出一个序列,根据冒泡算法,问数字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("\n"); 53 } 54 }
时间: 2024-10-13 04:55:20