hdu5497 Inversion
来源:互联网 发布:mac 切换大小写设置 编辑:程序博客网 时间:2024/05/21 14:01
Problem Description
You have a sequence {a1,a2,...,an} and you can delete a contiguous subsequence of length m . So what is the minimum number of inversions after the deletion.
Input
There are multiple test cases. The first line of input contains an integer T , indicating the number of test cases. For each test case:
The first line contains two integersn,m(1≤n≤105,1≤m<n) - the length of the seuqence. The second line contains n integers a1,a2,...,an(1≤ai≤n) .
The sum ofn in the test cases will not exceed 2×106 .
The first line contains two integers
The sum of
Output
For each test case, output the minimum number of inversions.
Sample Input
23 11 2 34 24 1 3 2
Sample Output
01
这场bc的题解虽然很难懂,但是弄明白后觉得写的很好。
令gi表示在i前面比ai大的数的个数, fi表示在i后面比ai小的数的个数, 这两个都可以用树状数组轻松求出来. 那么对于一个长度L的连续子序列, 删掉它之后逆序对减少的个数就是这段区间中gi的和 + 这段区间fi的和 - 这段区间的逆序对个数. 求区间逆序对个数只要用一个树状数组维护就好了, 每次只是删除最左端的一个数和加入最右端的一个数, 分别统计下贡献.
这里删除一段区间而少的逆序对其实就是区间左边每个数比区间大的数的和以及区间右边比区间内部小的数的个数和,还有区间本身的逆序对。
这里用树状数组的时候要注意,不要总是更新到maxn ,更新到n就行了,不然会超时。
#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<vector>#include<map>#include<set>#include<queue>#include<stack>#include<string>#include<algorithm>using namespace std;#define ll long long#define inf 0x7fffffff#define maxn 100100ll sum1[maxn],sum2[maxn];ll b[maxn+10],f[maxn],g[maxn],a1[maxn],a[maxn];int n;ll lowbit(ll x){ return x&(-x);}void update(ll pos,ll num){ while(pos<=n){ b[pos]+=num;pos+=lowbit(pos); }}ll getsum(ll pos){ ll num=0; while(pos>0){ num+=b[pos];pos-=lowbit(pos); } return num;}void clear(){ int i; for(i=1;i<=n+1;i++)b[i]=0;}int main(){ int m,i,j,T,tot; ll ans,cnt; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%lld",&a[i]); } clear(); sum1[0]=sum2[n+1]=0; for(i=1;i<=n;i++){ g[i]=getsum(n)-getsum(a[i]); update(a[i],1); sum1[i]=sum1[i-1]+g[i]; } clear(); for(i=n;i>=1;i--){ f[i]=getsum(a[i]-1); update(a[i],1); } for(i=1;i<=n;i++)sum2[i]=sum2[i-1]+f[i]; clear(); cnt=ans=0; for(i=m;i>=1;i--){ ans+=getsum(a[i]-1); update(a[i],1); } cnt=sum1[m]+sum2[m]-ans; for(i=2;i+m-1<=n;i++){ ans-=getsum(a[i-1]-1); update(a[i-1],-1); ans+=getsum(n)-getsum(a[i+m-1]); update(a[i+m-1],1); if(cnt<sum1[i+m-1]-sum1[i-1]+sum2[i+m-1]-sum2[i-1]-ans){ cnt=sum1[i+m-1]-sum1[i-1]+sum2[i+m-1]-sum2[i-1]-ans; } } printf("%lld\n",sum2[n]-cnt); } return 0;}
0 0
- hdu5497 Inversion
- hdu5497 Inversion 树状数组 待补完!!!
- hdu5497
- bestcoder#58 Inversion 即 hdu5497 (树状数组维护逆序数)
- hdu5497(树状数组模板)
- inversion
- Inversion
- Inversion
- HDU5497 (梳状数组套two pointers)
- zoj1201--------Inversion
- count inversion
- HDU4911-Inversion
- HDU4911:Inversion
- FOJ2166 inversion
- mobius inversion
- priority inversion
- hdu4911 Inversion
- sduacmDiv1-Inversion
- Objective-C NSFileManager 管理文件和目录
- C程序中丢弃输入行无用的代码
- iOS软件开发 Core Data的使用
- 我的SBJson来生成和解析JSON串的代码
- Gym 100685G Gadget Hackwrench (LCA)
- hdu5497 Inversion
- 求解集合A与B的差集
- Merge Two Sorted Lists and Merge k Sorted Lists
- 剑指offer—数组中的逆序对
- Android创建和删除文件夹和文件
- HDU 2064 汉诺塔III
- struts2笔记2
- CAN总线基础知识(一)
- CAN总线基础知识(二)