hdu 4911 求逆序对数+树状数组
生活随笔
收集整理的這篇文章主要介紹了
hdu 4911 求逆序对数+树状数组
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://acm.hdu.edu.cn/showproblem.php?pid=4911
給定一個序列,有k次機會交換相鄰兩個位置的數,問說最后序列的逆序對數最少為多少。
實際上每交換一次能且只能減少一個逆序對,所以問題轉換成如何求逆序對數。
歸并排序或者樹狀數組都可搞
樹狀數組:
先按大小排序后分別標號,然后就變成了求1~n的序列的逆序數,每個分別查詢出比他小的用i減,在把他的值插入即可
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define clr0(x) memset(x,0,sizeof(x)) typedef long long LL; typedef pair<int,int> p;const int maxn=100005; LL f[maxn]; int n; void add(int x,LL y) {for(;x<=n;x += x&(-x)) f[x]+=y; } LL sum(int x){LL s=0;for (;x;x -= x&(-x)) s+=f[x];return s; }p a[maxn]; int k;bool cmp(p i,p j){return i.second < j.second; }int main(){int i;LL s;while (~RD2(n,k)){for (i=0;i<n;++i){RD(a[i].first);a[i].second=i;}sort(a,a+n);for (i=0;i<n;++i)a[i].first = i+1;sort(a,a+n,cmp);clr0(f);for (s=i=0;i<n;++i){s += i - sum(a[i].first);add(a[i].first,1);}printf("%I64d\n",max(0LL,s-k));}return 0; }歸并排序:
每次歸并發現需要前后交換時都給總的ret加上mid - mvl + 1,因為mvl到mid直接的數都比mvr下標上的數大
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <queue> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define RD(x) scanf("%d",&x) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define clr0(x) memset(x,0,sizeof(x)) typedef long long LL; const int maxn = 1e5+5; LL k; int n, a[maxn], b[maxn];LL merge_sort(int l, int r) {if (l == r)return 0;int mid = (l + r) / 2;LL ret = merge_sort(l, mid) + merge_sort(mid+1, r);int mvl = l, mvr = mid+1, mv = l;while (mvl <= mid || mvr <= r) {if (mvr > r || (mvl <= mid && a[mvl] <= a[mvr])) {b[mv++] = a[mvl++];} else {ret += mid - mvl + 1;b[mv++] = a[mvr++];}}for (int i = l; i <= r; i++)a[i] = b[i];return ret; }int main () {while (scanf("%d%I64d", &n, &k) == 2) {for (int i = 1; i <= n; i++)RD(a[i]);printf("%I64d\n", max(merge_sort(1, n) - k, 0LL));}return 0; }轉載于:https://www.cnblogs.com/zibaohun/p/4046769.html
總結
以上是生活随笔為你收集整理的hdu 4911 求逆序对数+树状数组的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的第一个可用的Windows驱动完成了
- 下一篇: JBOSS通过Apache负载均衡方法一