HDU 1394 Minimum Inversion Number (线段树求逆序数 )
2015-04-05 09:54
387 查看
#include "string" #include "iostream" #include "cstdio" #include "cmath" #include "set" #include "queue" #include "vector" #include "cctype" #include "sstream" #include "cstdlib" #include "cstring" #include "stack" #include "ctime" #include "algorithm" #define pa pair<int,int> #define Pi M_PI #define INF 0x3f3f3f3f #define INFL 0x3f3f3f3f3f3f3f3fLL using namespace std; typedef long long LL; const int M=5005; //#define M 200005 int sum[M<<2]; //int ans=0,ans1=0; inline void PushPlus(int rt) { //sum[rt] = max(sum[rt<<1] , sum[rt<<1|1]); sum[rt] =sum[rt<<1] +sum[rt<<1|1]; } void Build(int l, int r, int rt) { if(l == r) { // scanf("%d", &sum[rt]); sum[rt]=0; return ; } int m = ( l + r )>>1; Build(l,m,rt<<1); Build(m+1,r,rt<<1|1); PushPlus(rt); } /* void build(int node, int begin, int end) { */ void Update(int p, int l, int r, int rt) { if( l == r ) { sum[rt] ++; return ; } int m = ( l + r ) >> 1; if(p <= m) Update(p, l,m,rt<<1); else Update(p, m+1,r,rt<<1|1); PushPlus(rt); } int Query(int L,int R,int l,int r,int rt) { if( L <= l && r <= R ) { return sum[rt]; } int m = ( l + r ) >> 1; //int ans=0,ans1=0; int ans=0; if(L<=m) ans+=Query(L,R,l,m,rt<<1); if(R>m) ans+=Query(L,R,m+1,r,rt<<1|1); //int ans=0; return ans; } int main() { // int T, n, a, b; // // scanf("%d",&T); // // for( int i = 1; i <= T; ++i ) // // { // // printf("Case %d:\n",i); // int m; // scanf("%d%d",&n,&m); // // Build(1,n,1); // char op[2]; // //ans=0,ans1=0; // while(m--) // { // scanf("%s%d%d",op,&a,&b); // // cin>>op>>a>>b; // // scanf("%d %d", &a, &b); // if(op[0] == 'Q') // printf("%d\n",Query(a,b,1,n,1)); // if(op[0] == 'U') // Updata(a,b,1,n,1); /*//*/ // } // // } // int n , m; // while (~scanf("%d%d",&n,&m)) { // Build(1 , n , 1); // int i; // for( i = 1; i<=20; ++i) // cout<< "seg"<< i << "=" <sum[i] <<endl; // while (m --) { // char op[2]; // int a , b; // scanf("%s%d%d",op,&a,&b); // if (op[0] == 'Q') printf("%d\n",Query(a , b , 1 , n , 1)); // else Updata(a , b , 1 , n , 1); // } // } // return 0; int x[M]; int n; while (~scanf("%d",&n)) { Build(0 , n - 1 , 1); int sum = 0; for (int i = 0 ; i < n ; i ++) { scanf("%d",&x[i]);//找出比当前节点大的数加起来就可以得到逆序数了 sum += Query(x[i] , n - 1 , 0 , n - 1 , 1); Update(x[i] , 0 , n - 1 , 1); } int ret = sum; for (int i = 0 ; i < n ; i ++) { sum += n - x[i] - x[i] - 1; ret = min(ret , sum); } printf("%d\n",ret); } return 0; }
首先按顺序把序列a[i]每个数插入到树状数组中,插入的内容是1,表示放了一个数到树状数组中。
然后使用sum操作获取当前比a[i]小的数,那么当前i - sum则表示当前比a[i]大的数,如此反复直到所有数都统计完,
比如
4 3 1 2
i = 1 : 插入 4 : update(4,1),sum(4)返回1,那么当前比4大的为 i - 1 = 0;
i = 2 : 插入 3 : update(3,1),sum(3)返回1,那么当前比3大的为 i - 1 = 1;
i = 3 : 插入 1 : update(1,1),sum(1)返回1,那么当前比1大的为 i - 1 = 2;
i = 4 : 插入 2 : update(2,1),sum(2)返回2,那么当前比2大的为 i - 2 = 2;
过程很明了,所以逆序数为1+2+2=5
相关文章推荐
- HDU 1394 Minimum Inversion Number (线段树 单点更新 求逆序数)
- HDU 1394 Minimum Inversion Number(归并排序 线段树 逆序数)
- hdu 1394 Minimum Inversion Number 线段树求逆序数
- HDU 1394 Minimum Inversion Number(线段树求逆序数)
- HDU 1394- Minimum Inversion Number(线段树求逆序数)
- HDU 1394 Minimum Inversion Number(线段树求最小逆序数对)
- HDU 1394 Minimum Inversion Number 线段树求逆序数
- hdu 1394 Minimum Inversion Number || ZOJ Monthly, January 2003 || 线段树 + 逆序数
- hdu 1394 Minimum Inversion Number(线段树求最小逆序数)
- HDU 1394 Minimum Inversion Number(线段树:单点更新,求逆序数)
- HDU - 1394 Minimum Inversion Number (线段树求逆序数)
- HDU - 1394 Minimum Inversion Number (线段树求逆序数)
- hdu 1394 Minimum Inversion Number (线段树求逆序数)
- hdu 1394 Minimum Inversion Number 线段树 逆序数
- hdu 1394 Minimum Inversion Number 线段树求最小逆序数
- hdu 1394 Minimum Inversion Number 用线段树求0到n-1的排列的逆序数
- HDU 1394 Minimum Inversion Number(线段树,逆序数)
- HDU 1394 Minimum Inversion Number // 线段树求逆序数
- hdu 1394 Minimum Inversion Number(线段树之 单点更新求逆序数)
- HDU 1394 Minimum Inversion Number(线段树求逆序数啊)