本题为是对逆序对的查找,问题可为在某个区间共有多少个数被输入,首先为查找初始的逆序对数,然后求将第一个数加入到最后的逆序对数,设初始的逆序对数总共为SUM这将第一个数加入到最后的的逆序对数为SUM加上比A1大的数减去比A1小的数字。即为当前的逆序对数,如此类推,求的比逆序对数最小的。。。
View Code
#include<cstdio> #include<cstdlib> #include<cstdlib> #include<cstring> #define MAXN 5010 int seg_tree[MAXN<<2]; void build_tree(int l,int r,int id); int query_tree(int left,int right,int l,int r,int id); void update_tree(int left,int right,int l,int r,int id); void push_up_tree(int id); int x[MAXN]; int main() { int n,i,j,k,sum; while(scanf("%d",&n)==1) { sum=0; build_tree(0,n-1,1); for(i=0;i<n;i++) { scanf("%d",x+i); } for(i=n-1;i>=0;i--) { sum+=query_tree(0,x[i],0,n-1,1); update_tree(x[i],x[i],0,n-1,1); } int ret=sum; for(i=0;i<n;i++) { sum+=n-1-x[i]-x[i]; if(ret>sum) ret=sum; } printf("%d\n",ret); } } void build_tree(int l,int r,int id) { if(l==r) {seg_tree[id]=0; return ; } int m=(l+r)>>1; build_tree(l,m,id<<1); build_tree(m+1,r,id<<1|1); push_up_tree(id); } int query_tree(int left,int right,int l,int r,int id) { if(left<=l&&right>=r) return seg_tree[id]; int m=(l+r)>>1,ret=0; if(left<=m) ret+=query_tree(left,right,l,m,id<<1); if(right>m) ret+=query_tree(left,right,m+1,r,id<<1|1); return ret; } void update_tree(int left,int right,int l,int r,int id) { if(l==r) {seg_tree[id]++; return ; } int m=(l+r)>>1; if(left<=m) update_tree(left,right,l,m,id<<1); else update_tree(left,right,m+1,r,id<<1|1); push_up_tree(id); } void push_up_tree(int id) { seg_tree[id]=seg_tree[id<<1]+seg_tree[id<<1|1]; }