题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1394
题意:
a1, a2, …, an-1, an
a2, a3, …, an, a1
a3, a4, …, an, a1, a2
…
an, a1, a2, …, an-1
求其中最小的逆序数的个数
题解:
从a[0]开始扫描,找比a[0]大的个数,也就是询问区间(a[0],n-1)中点的个数,然后再插入a[0],更新父节点
求最小:设逆序数为sum,x[0]后面比它小的一定是x[0]个。那么移到末尾后,比x[0]大的数的后面比它小的数统统加一,也就是加(n - a[0] - 1),然后它放到末尾了,他原来的后面比它小的数变为0,也就是sum = sum + (n - a[0] - 1) - a[0];’
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 #define MS(a) memset(a,0,sizeof(a)) 5 #define MP make_pair 6 #define PB push_back 7 const int INF = 0x3f3f3f3f; 8 const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; 9 inline ll read(){ 10 ll x=0,f=1;char ch=getchar(); 11 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return x*f; 14 } 15 ////////////////////////////////////////////////////////////////////////// 16 const int maxn = 1e5+10; 17 18 int sum[maxn<<2],x[maxn]; 19 20 void pushup(int rt){ 21 sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 22 } 23 24 void build(int l,int r,int rt){ 25 sum[rt] = 0; 26 if(l == r) return; 27 int mid = (l+r)/2; 28 build(l,mid,rt<<1); 29 build(mid+1,r,rt<<1|1); 30 } 31 32 void update(int l,int r,int rt,int p){ 33 if(l == r){ 34 sum[rt] = 1; 35 return ; 36 } 37 38 int mid = (l+r)/2; 39 if(p <= mid) 40 update(l,mid,rt<<1,p); 41 else if(p > mid) 42 update(mid+1,r,rt<<1|1,p); 43 pushup(rt); 44 } 45 46 int query(int l,int r,int rt, int L,int R){ 47 if(L<=l && r<=R) 48 return sum[rt]; 49 50 int mid = (l+r)/2; 51 int ans = 0; 52 // if(L>mid) 53 // ans += query(mid+1,r,rt<<1|1,L,R); 54 // else if(R<mid) 55 // ans += query(l,mid,rt<<1,L,R); 56 // else 57 // ans += query(l,mid,rt<<1,L,R)+query(mid+1,r,rt<<1|1,L,R); 58 if(L<=mid) 59 ans += query(l,mid,rt<<1,L,R); 60 if(R>mid) 61 ans += query(mid+1,r,rt<<1|1,L,R); 62 return ans; 63 } 64 65 int main(){ 66 int n; 67 while(cin>>n){ 68 int s = 0; 69 build(0,n-1,1); 70 for(int i=0; i<n; i++){ 71 scanf("%d",&x[i]); 72 s += query(0,n-1,1,x[i],n-1); 73 update(0,n-1,1,x[i]); 74 } 75 76 int ans = s; 77 for(int i=0; i<n; i++){ 78 s = s + (n-x[i]-1) - x[i]; 79 ans = min(ans,s); 80 } 81 82 cout << ans << endl; 83 } 84 85 return 0; 86 }