洛谷P1966 火柴排隊 貪心+離散化+逆序對 (待補充QAQ
題目描述
description
涵涵有兩盒火柴,每盒裝有 n 根火柴,每根火柴都有一個高度。 現在將每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 兩列火柴之間的距離定義為:∑(ai??bi?)2
其中ai? 表示第一列火柴中第ii個火柴的高度,bi?表示第二列火柴中第 i 個火柴的高度。
每列火柴中相鄰兩根火柴的位置都可以交換,請你通過交換使得兩列火柴之間的距離最小。請問得到這個最小的距離,最少需要交換多少次?如果這個數字太大,請輸出這個最小交換次數對 99,999,997取模的結果。
Input
共三行,第一行包含一個整數n,表示每盒中火柴的數目。
第二行有n個整數,每兩個整數之間用一個空格隔開,表示第一列火柴的高度。
第三行有n 個整數,每兩個整數之間用一個空格隔開,表示第二列火柴的高度。
Output
一個整數,表示最少交換次數對 99,999,997取模的結果。
Sample Input
#1:4 2 3 1 4 3 2 1 4#2:
4
1 3 4 2
1 7 2 4
Sample Output
#1:1
#2:2
HINT
#1
最小距離是0,最少需要交換 1次,比如:交換第1列的前2 根火柴或者交換第 2 列的前2根火柴。
#2
最小距離是 1010,最少需要交換22次,比如:交換第11 列的中間22根火柴的位置,再交換第22 列中後 22 根火柴的位置。
【數據範圍】
對於 10%的數據, 1 ≤ n ≤ 101≤n≤10;
對於 30%的數據,1 ≤ n ≤ 1001≤n≤100;
對於 60%的數據,1 ≤ n ≤ 1,000 1≤n≤1,000;
對於 100%的數據,1≤n≤100,000,0≤火柴高度≤ maxlongint
正解:
貪心+離散化+逆序對
解題報告:
這題其實主要難在想方法吧我覺得?學長提點了下說用貪心之後就大概明白了,感覺沒有很難
但是離散化這裏還是挺有趣的,因為並不是能很熟練地掌握離散化(昂其實理解得還不錯……主要實現太少TT)
所以在這裏放一下,難得自己想出離散化然後手打出來,實在覺得可喜可賀忍不住放上來(對我大概就是在炫耀xxx
代碼↓(這個真滴整個純手打,全程自己推出來的,有點兒驕傲嘻嘻嘻
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct str 4 { 5 long long hei,id; 6 }mat1[1000010],mat2[1000010]; 7 long long f[1000010],g[1000010],p[1000010],ans; 8 long long read() 9 { 10 char ch=getchar();long long x=0,y=1; 11 while((ch>‘9‘ || ch<‘0‘) && ch!=‘-‘)ch=getchar(); 12 if(ch==‘-‘)y=-1,ch=getchar(); 13 while(ch>=‘0‘ && ch<=‘9‘)x=(x<<1)+(x<<3)+(ch^‘0‘),ch=getchar(); 14 return x*y; 15 } 16 bool cmp(str x,str y) 17 { 18 return x.hei<y.hei; 19 } 20 void gbpx(long long l,long long r) 21 { 22 long long i=l,k=l,m=(l+r)/2,j=m+1; 23 if(l==r)return; 24 gbpx(l,m); 25 gbpx(m+1,r); 26 while(i<=m && j<=r) 27 { 28 if(g[i]<=g[j]) 29 { 30 p[k]=g[i]; 31 i++; 32 k++; 33 } 34 else 35 { 36 p[k]=g[j]; 37 j++; 38 k++; 39 ans=(ans+m-i)+1%99999997; 40 } 41 } 42 while(i<=m) 43 { 44 p[k]=g[i]; 45 i++; 46 k++; 47 } 48 while(j<=r) 49 { 50 p[k]=g[j]; 51 j++; 52 k++; 53 } 54 for(i=l;i<=r;i++)g[i]=p[i]; 55 return; 56 } 57 int main() 58 { 59 long long n=read(); 60 for(long long i=1;i<=n;i++)mat1[i].hei=read(),mat1[i].id=i; 61 sort(mat1+1,mat1+n+1,cmp); 62 for(long long i=1;i<=n;i++)f[mat1[i].hei]=mat1[i].id; 63 for(long long i=1;i<=n;i++)mat2[i].hei=read(),mat2[i].id=i; 64 sort(mat2+1,mat2+n+1,cmp); 65 for(long long i=1;i<=n;i++)g[mat2[i].id]=f[i]; 66 gbpx(1,n); 67 printf("%lld",ans%99999997); 68 return 0; 69 }
ps:
逆序對我用的歸並排序,但是聽說用樹狀數組很簡單
然而我太弱了不會樹狀數組所以也是學了樹狀數組之後補一個樹狀數組求線段樹的版本quq
再,psssssss:
洛谷上的題目復制來真滴好麻煩……所有字母都會出現兩次……煩躁……
然後又很強迫癥地希望能題目描述格式一樣……搞了半天……以後就不要強迫癥算了在這兒調格式真滴就是在浪費時間TT或者實在犯強迫癥了去BZOJ上找下有乜有同樣的題目復制來就是了quq
洛谷P1966 火柴排隊 貪心+離散化+逆序對 (待補充QAQ