hlgHCPC2014校赛训练赛 1 BB.序列问题
题目:
计算序列 a[] 中, 当 i < j < k, a[i] < a[j]&&a[j] > a[k], (a[i]和a[k]无需比较大小)这样的子序列个数。
Input
多组输入数据:
每组数据第一行一个数n:代表序列长度为n(0<n<50000);
接下来第二行有n个数:代表序列元素的值a[i](0<a[i]<50000,且任意2个元素的值不相同)。
Output
对于每组数据输出符合条件的子序列的个数,每个输出占一行。
Sample Input
5
1 3 5 2 4
Sample Output
5
这个题目是小白书上乒乓比赛的变形 (变简单了。。额……)
题目有一步优化 ,先对数值排序 (这样的话如果n比较小的话,每次的求sum与add会比较省时间)
代码一:
这个代码应该会过:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<string.h> 3 #include<stdio.h> 4 #include<algorithm> 5 using namespace std; 6 7 int lowbit(int x) 8 { 9 return x&(-x); 10 } 11 12 int n; 13 const int maxn=50005; 14 int c[maxn]; 15 16 void add(int i,int num) 17 { 18 while(i<=n) 19 { 20 c[i]+=num; 21 i+=lowbit(i); 22 } 23 } 24 25 int getsum(int i) 26 { 27 int sum=0; 28 while(i>0) 29 { 30 sum+=c[i]; 31 i-=lowbit(i); 32 } 33 return sum; 34 } 35 36 struct point 37 { 38 int num; 39 int id; 40 }poin[maxn]; 41 42 43 bool cmp(point p1,point p2) 44 { 45 return p1.num<p2.num; 46 } 47 48 int summ[maxn]; 49 50 int main() 51 { 52 freopen("aa.txt","r",stdin); 53 while(scanf("%d",&n)!=EOF) 54 { 55 memset(c,0,sizeof(c)); 56 for(int i=0;i<n;i++) 57 { 58 scanf("%d",&poin[i].num); 59 poin[i].id=i+1; 60 } 61 sort(poin,poin+n,cmp); 62 long long int ans=0; 63 for(int i=0;i<n;i++) 64 { 65 ans+=getsum(poin[i].id)*(getsum(n)-getsum(poin[i].id)); 66 add(poin[i].id,1); 67 } 68 printf("%lld\n",ans); 69 } 70 return 0; 71 }
底下的代码留着oj加题的时候测试一下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<string.h> 3 #include<stdio.h> 4 #include<algorithm> 5 using namespace std; 6 7 int lowbit(int x) 8 { 9 return x&(-x); 10 } 11 12 const int maxn=50005; 13 int c[maxn]; 14 15 void add(int i,int num) 16 { 17 while(i<=50000) 18 { 19 c[i]+=num; 20 i+=lowbit(i); 21 } 22 } 23 24 int getsum(int i) 25 { 26 int sum=0; 27 while(i>0) 28 { 29 sum+=c[i]; 30 i-=lowbit(i); 31 } 32 return sum; 33 } 34 int a[maxn]; 35 36 int summ[maxn]; 37 38 int main() 39 { 40 int n; 41 freopen("aa.txt","r",stdin); 42 while(scanf("%d",&n)!=EOF) 43 { 44 memset(c,0,sizeof(c)); 45 long long int ans=0; 46 for(int i=1;i<=n;i++) 47 { 48 scanf("%d",&a[i]); 49 ans+=getsum(a[i])*(getsum(50000)-getsum(a[i])); 50 add(a[i],1); 51 }printf("%lld\n",ans); 52 } 53 return 0; 54 }