日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

hdu 4911 求逆序对数+树状数组

發(fā)布時(shí)間:2024/4/15 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu 4911 求逆序对数+树状数组 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://acm.hdu.edu.cn/showproblem.php?pid=4911

給定一個(gè)序列,有k次機(jī)會(huì)交換相鄰兩個(gè)位置的數(shù),問(wèn)說(shuō)最后序列的逆序?qū)?shù)最少為多少。


實(shí)際上每交換一次能且只能減少一個(gè)逆序?qū)?#xff0c;所以問(wèn)題轉(zhuǎn)換成如何求逆序?qū)?shù)。

歸并排序或者樹狀數(shù)組都可搞

樹狀數(shù)組:

先按大小排序后分別標(biāo)號(hào),然后就變成了求1~n的序列的逆序數(shù),每個(gè)分別查詢出比他小的用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; }


歸并排序:

每次歸并發(fā)現(xiàn)需要前后交換時(shí)都給總的ret加上mid - mvl + 1,因?yàn)閙vl到mid直接的數(shù)都比mvr下標(biāo)上的數(shù)大

#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; }

轉(zhuǎn)載于:https://www.cnblogs.com/zibaohun/p/4046769.html

總結(jié)

以上是生活随笔為你收集整理的hdu 4911 求逆序对数+树状数组的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。