HDU 1394--线段树(求逆序数)||暴力
http://acm.hdu.edu.cn/showproblem.php?pid=1394
题意:
给你一个有0--n-1数字组成的序列,然后进行这样的操作,每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,那么每个序列都有一个逆序数,找出其中最小的一个输出!
这里有个技巧,就是算完第一组的逆序数后,后面移动得来的逆序数可有sum+n-a[i]-1-a[i]得;
暴力写法: 250ms
View Code
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 int main() 5 { 6 int n,i,a[5050],j; 7 while(~scanf("%d",&n)) 8 { 9 int sum=0; 10 for(i=0;i<n;i++) 11 scanf("%d",&a[i]); 12 for(i=0;i<n;i++) 13 for(j=i+1;j<n;j++) 14 if(a[i]>a[j]) 15 sum++; 16 int Min=sum; 17 for(i=0;i<n-1;i++) 18 { 19 sum=sum+n-a[i]-a[i]-1; 20 if(Min>sum) 21 Min=sum; 22 } 23 printf("%d\n",Min); 24 } 25 return 0; 26 }
线段树写法: 46ms
View Code
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define maxn 5050 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 int sum[maxn<<2]; 8 void Pushup(int rt) 9 { 10 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 11 } 12 void build(int l,int r,int rt) 13 { 14 if(l==r) 15 { 16 sum[rt]=0; 17 return; 18 } 19 int m=(l+r)>>1; 20 build(lson); 21 build(rson); 22 Pushup(rt); 23 } 24 void update(int pos,int l,int r,int rt) 25 { 26 if(l==r) 27 { 28 sum[rt]++; 29 return; 30 } 31 int m=(l+r)>>1; 32 if(pos<=m) update(pos,lson); 33 else update(pos,rson); 34 Pushup(rt); 35 } 36 int quary(int L,int R,int l,int r,int rt) 37 { 38 if(L<=l&&R>=r) 39 return sum[rt]; 40 int m=(l+r)>>1; 41 int ret=0; 42 if(L<=m) ret+=quary(L,R,lson); 43 if(R>m) ret+=quary(L,R,rson); 44 return ret; 45 } 46 int main() 47 { 48 int n,a[5050],i; 49 while(~scanf("%d",&n)) 50 { 51 build(0,n-1,1); 52 int sum=0; 53 for(int i=0;i<n;i++) 54 { 55 scanf("%d",&a[i]); 56 if(a[i]!=n-1) 57 sum+=quary(a[i],n-1,0,n-1,1); 58 update(a[i],0,n-1,1); 59 } 60 int Min=sum; 61 for(i=0;i<n-1;i++) 62 { 63 sum=sum+n-a[i]-1-a[i]; 64 if(Min>sum) 65 Min=sum; 66 } 67 printf("%d\n",Min); 68 } 69 return 0; 70 }
posted on 2013-02-06 21:47 acoderworld 阅读(86) 评论(0) 收藏 举报

浙公网安备 33010602011771号