HDU 1394 Minimum Inversion Number
2013-09-14 00:05
281 查看
找以前的水题切,但是忘记以前怎么想的呢,TAT...
于是乎重新推了一次,找到了新的规律,时间复杂度大概是O(nlogn)+O(n^2)+O(n);如果数据规模还大一点就TLE了。。。
首先求出逆序对数,对于初始队列维护四个值:
1、第一个值为左边比A[i]大的数Left[i];
2、左边比A[i]小的数Left2[i];
3、右边比A[i]大的数Right[i];
4、第i个数A[i]的逆序对数d[A[i]];
然后循环移位时可以发现一个规律,即新的数列逆序对数为:
当前逆序对数(Si)-(d[A[i]])-Left2[i]+Left[i]+Right[i];
于是乎重新推了一次,找到了新的规律,时间复杂度大概是O(nlogn)+O(n^2)+O(n);如果数据规模还大一点就TLE了。。。
首先求出逆序对数,对于初始队列维护四个值:
1、第一个值为左边比A[i]大的数Left[i];
2、左边比A[i]小的数Left2[i];
3、右边比A[i]大的数Right[i];
4、第i个数A[i]的逆序对数d[A[i]];
然后循环移位时可以发现一个规律,即新的数列逆序对数为:
当前逆序对数(Si)-(d[A[i]])-Left2[i]+Left[i]+Right[i];
#include <iostream> #include <cstdlib> #include <cstdio> #include <string> #include <cstring> #include <cmath> #include <vector> #include <queue> #include <algorithm> #include <map> #include <stack> using namespace std; const int maxn = 5000 + 100; const int INF = 0x3f3f3f3f; void readint(int &x) { char c = getchar(); while(!isdigit(c)) c = getchar(); x = 0; while(isdigit(c)) { x = x*10+c-'0'; c = getchar(); } } void writeint(int x) { if(x > 9) writeint(x/10); putchar(x%10+'0'); } int sumv[maxn<<2]; int A[maxn]; int Left[maxn], Right[maxn]; int Left2[maxn]; int d[maxn]; void pushup(int o) { sumv[o] = sumv[o*2]+sumv[o*2+1]; } void build(int o, int L, int R) { if(L == R) { sumv[o] = 0; return ; } int M = L+(R-L)/2; build(o*2, L, M); build(o*2+1, M+1, R); pushup(o); } void update(int o, int L, int R, int p, int v) { if(L == R) { sumv[o] = v; return ; } int M = L+(R-L)/2; if(p <= M) update(o*2, L, M, p, v); else update(o*2+1, M+1, R, p, v); pushup(o); } int query(int o, int L, int R, int ql, int qr) { if(ql <= L && qr >= R) return sumv[o]; int M = L+(R-L)/2, ans = 0; if(ql <= M) ans += query(o*2, L, M, ql, qr); if(qr > M) ans += query(o*2+1, M+1, R, ql, qr); return ans; } int n; int main() { while(~scanf("%d", &n)) { memset(Left, 0, sizeof(Left)); memset(Right, 0, sizeof(Right)); memset(Left2, 0, sizeof(Left2)); for(int i = 1; i <= n; i++) { readint(A[i]); A[i]++; } for(int i = 1; i <= n; i++) { for(int j = 1; j <= i; j++) { if(A[j] > A[i]) Left[i]++; if(A[j] < A[i]) Left2[i]++; } for(int j = i+1; j <= n; j++) if(A[j] > A[i]) Right[i]++; } build(1, 1, n); int ans = 0; for(int i = n; i >= 1; i--) { int t = query(1, 1, n, 1, A[i]); update(1, 1, n, A[i], 1); d[A[i]] = t; ans += t; } int pre = 0, res = ans; for(int i = 1; i <= n-1; i++) { pre = res; res = pre-d[A[i]]-Left2[i]+Left[i]+Right[i]; ans = min(ans, res); } writeint(ans), puts(""); } return 0; }
相关文章推荐
- 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
- HDU 1394 Minimum Inversion Number【线段树,归并排序,树状数组】
- HDU 1394 Minimum Inversion Number(单点更新)
- hdu 1394 Minimum Inversion Number
- HDU1394 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 // 线段树求逆序数
- HDU 1394 Minimum Inversion Number 【逆序数】