HDU 1394 Minimum Inversion Number (暴力+線段樹)
Minimum Inversion Number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 20570 Accepted Submission(s): 12335
Problem Description
The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
Input
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
Output
For each case, output the minimum inversion number on a single line.
Sample Input
10
1 3 6 9 0 8 5 7 4 2
Sample Output
16
Author
CHEN, Gaoli
Source
題意:
重複一次操作可以把最前面的樹放到最後面。求最小的逆序總數,逆序數是i<j且Ai>Bi。
POINT:
因為給你N後數是確定的,是0-(n-1),所以只要知道最前面的數的值,就可以知道把它移到後面後逆序總數的變化。
比第一個小的數量必為Ai, 大的必為n-Ai-1。這是這題的關鍵。
下面則是要先算出初始狀態時的逆序總數,再根據它一次一次移動求出每個的逆序總數,在和ans比較。
這裡有兩種方法求初始狀態時的逆序總數。
法1:暴力,每輸入一個數,去找前面有幾個比他大的,記錄答案。顯然這個非常簡單。
法2:利用線段樹,此時的線段樹的區間直接代表數值,存的則是這些數出現了幾次。
即num[x]代表值在l和r的數出現了幾次。也是每輸入一個數,存下這個數,更新區間,再去詢問一次Ai+1到n+1的數出現了幾次。
法1:顯然比線段樹短很多,但是也慢很多。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
const int N = 5000+5;
int a[N];
int sum[N];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(sum,0,sizeof sum);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
for(int j=1;j<i;j++)
{
if(a[j]>a[i])
{
sum[i]++;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
ans+=sum[i];
}
int pre=ans;
for(int i=1;i<=n;i++)
{
int now=pre;
int xiao=a[i];
int da=n-a[i]-1;//不包括自己
pre=now+da-xiao;
ans=min(ans,pre);
}
printf("%d\n",ans);
}
法2:
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
using namespace std;
const int N = 5000*4;
int a[N/4];
int num[N];
void add(int x,int l,int r,int now)
{
if(l==r&&r==now) num[x]++;
else
{
int mid=(l+r)>>1;
if(now<=mid) add(x*2,l,mid,now);
if(mid<now) add(2*x+1,mid+1,r,now);
num[x]=num[2*x+1]+num[x*2];
}
}
int query(int x,int l,int r,int ll,int rr)
{
int ans=0;
if(ll<=l&&rr>=r) ans=num[x];
else
{
int mid=(l+r)>>1;
if(ll<=mid) ans+=query(x*2,l,mid,ll,rr);
if(mid<rr) ans+=query(2*x+1,mid+1,r,ll,rr);
}
return ans;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(num,0,sizeof num);
int ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(1,0,n-1,a[i]);
ans+=query(1,0,n-1,a[i]+1,n-1);
}
int pre=ans;
for(int i=1;i<=n;i++)
{
int now=pre;
now=pre-a[i]+n-a[i]-1;
ans=min(now,ans);
pre=now;
}
printf("%d\n",ans);
}
}
相關文章
- 線段樹 transformation——hdu 4578ORM
- hdu 1698 線段樹 一段更新染色
- HDU 3333 Turing Tree(線段樹+離線操作)
- [ABC337G] Tree Inversion(換根 dp + 值域線段樹)
- HDU 1556 Color the ball(線段樹|樹狀陣列)陣列
- HDH 1264 Counting Squares (線段樹+掃描線|暴力)
- HDU 2795 Billboard(線段樹 區間最大)
- Transformation HDU - 4578線段樹綜合操作ORM
- HDU2665 Kth number【主席樹】
- HDU 3074 Multiply game(線段樹 單點更新)GAM
- HDU 1542 Atlantis (線段樹+離散化+掃描線)
- HDU 1754 I Hate It (線段樹 區間最值)
- HDU 1166 敵兵佈陣 (線段樹 插點問線)
- HDU 1385 Minimum Transport Cost
- HDU 4027 Can you answer these queries? (線段樹 區間開方)
- HDU 1255 覆蓋的面積(線段樹+掃描線+離散化)
- 線段樹
- 線~段~樹
- HDU 3397 Sequence operation(線段樹區間染色加區間合併)
- HDU1754 I Hate It 【線段樹基礎:點修改+區間查詢】
- HDU 1711 Number Sequence(KMP)KMP
- 01 線段樹
- 線段樹--RMQMQ
- 【模版】線段樹
- 線段樹模板
- 線段樹 hate it
- [LeetCode] 2406. Divide Intervals Into Minimum Number of GroupsLeetCodeIDE
- CodeForces - 976A:Minimum Binary Number(水題)
- HDU1698 Just a Hook【線段樹基礎:區間修改+區間查詢】Hook
- ut.cpp 最大線段並減線段交 [線段樹]
- 李超線段樹
- 線段樹進階
- 權值線段樹
- 線段樹筆記筆記
- Segment Tree(線段樹)
- 線段樹入門
- HDU1166 敵兵佈陣【線段樹基礎:點修改+區間查詢】
- 洛谷題單指南-線段樹-P3373 【模板】線段樹 2