http://acm.hdu.edu.cn/showproblem.php?pid=1394
(1)先构造一棵线段树(初始化),然后按先后顺序依次处理每一个数。对每一个数需要两种操作:
1)查询已经入树的比该数大的数的个数;
2)将该数插入到线段树中。
(2)尝试过将1)和2)合并,只写一个函数,AC了。详细操作见代码2 。
具体代码:
View Code
#include<stdio.h> #include<string.h> #include<algorithm> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int N=5500; int data[N], sum[N<<2]; int n, m; int ans; void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l, int r, int rt) { if(l==r) { scanf("%d", &data[l]); sum[rt]=0; return ; } int m=l+r>>1; build(lson); build(rson); pushup(rt); } int query(int p, int l, int r, int rt) { if(p<=l) { return sum[rt]; } int m=l+r>>1; int ret=0; if(p<=m) ret+=query(p, lson); if(n>m) ret+=query(p, rson); return ret; } void insert(int val, int l, int r, int rt) { if(l==r) { sum[rt]=1; return ; } int m=l+r>>1; if(val<=m) insert(val, lson); else insert(val, rson); pushup(rt); } int main() { int i, j; while(scanf("%d", &n)!=EOF) { build(1, n, 1); ans=0; for(i=1;i<=n;i++) { ans+=query(data[i]+1, 1, n, 1); insert(data[i]+1, 1, n, 1); } int x=ans; for(i=1;i<=n;i++) { x-=data[i]-(n-1-data[i]); if(x<ans) ans=x; } printf("%d\n", ans); } return 0; }
代码2(边查询边更新):
View Code
#include<stdio.h> #include<string.h> #include<algorithm> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using namespace std; const int N=5500; int data[N], sum[N<<2]; int n, m; int ans; void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l, int r, int rt) { if(l==r) { scanf("%d", &data[l]); sum[rt]=0; return ; } int m=l+r>>1; build(lson); build(rson); pushup(rt); } void insert(int val, int s, int l, int r, int rt) { if(l==r) { sum[rt]=1; ans+=s; return ; } int m=l+r>>1; if(val<=m) insert(val, s+sum[rt<<1|1], lson); else insert(val, s, rson); pushup(rt); } int main() { int i, j; while(scanf("%d", &n)!=EOF) { build(1, n, 1); ans=0; for(i=1;i<=n;i++) { insert(data[i]+1, 0, 1, n, 1); } int x=ans; for(i=1;i<=n;i++) { x-=data[i]-(n-1-data[i]); if(x<ans) ans=x; } printf("%d\n", ans); } return 0; }