題目描述
給定 \(n\) 個元素,每個元素有兩個屬性值 \((a_i,b_i)\),我們可以將其以任意順序排列,要最大化下式:
\[\min(a_i+i\cdot k)-\max(b_i+i\cdot k)
\]\(n\leq 10^5,a_i,b_i,kn\leq 10^9\)
解法
應該是遇到困難退大火才對,直接使用列舉法,考慮列舉 \(m=\min(a_i+i\cdot k)\),那麼為了滿足這個 \(m\) 的限制,第 \(i\) 個元素的位置必須 \(\geq \lceil\frac\rceil\),我們記這個臨界值是 \(c_i\),那麼知道所有元素的 \(c_i\) 我們直接貪心,按照 \(b\) 下降的順序把數盡量的往前放,正確性有兩點:合法性一定能保證;用調整法可以證明 \(b\) 大的不必給後面留出前面的位置。
現在的問題在於確定這個 \(m\)(直接退火肯定是不行的),我們考慮確定它的大致範圍,首先我們把 \(a\) 從大到小排序,按照這個順序可以計算 \(m\) 的最大值 \(mx\),結論是 \(m\) 的取值一定在 \((mx-k,mx]\) 中。
證明可以考慮調整法,考慮我們把 \(m\) 調大 \(k\) 之後任然 \(\leq mx\),那麼此時我們考慮 \(\max(b_i+i\cdot k)\) 的變化即可,由於調大之後 \(c_i\) 都增加 \(1\),最壞情況是把所有位置向右平移(而且不可能實現),所以它至多增加 \(k\)
那麼有這個較精確的範圍就可以退火了。說一下細節:我們以 \(m\) 為退火的起點,每次就給乙個 \([0,k)\) 中的數增加乙個和溫度 \([-t,t]\) 中的隨機向量,然後卡準秒數退火即可,注意 \(d\) 設定為 \(0.98\) 較優秀(降溫速度較快)
總結
退火其實是很有講究的,並不是乙個模板可以走天下,下面就來談一談我的心得感悟:
#include #include #include #include #include #include using namespace std;
const int m = 100005;
const int inf = 2e9;
#define db double
const db d = 0.98;
int read()
while(c>='0' && c<='9')
return x*f;
}int n,k,mx,ans,c[m],d[m],fa[m];
struct node
}s[m];
int random(int x)
int random(int l,int r)
int find(int x)
int calc(int m)
int mx=0,mi=inf;
for(int i=1;i<=n;i++)
return mi-mx;
}void zxy()
}signed main()
省選集訓2022 模擬賽6
題目描述 定義長度為 n 的好串 s 滿足 給你長度為 n 的序列 a 和 v 分別表示原序列和價值序列。你每次可以選擇乙個原序列中的好串,將其刪除之後剩下的串會前後拼接。設這次刪除的長度是 l 那麼會得分 v l 問最大得分,不一定要把原序列刪完。n leq 400,v i leq 10 5,a ...
省選集訓2022 模擬賽8
題目描述 給定乙個 n times m 的 01 矩陣,對於矩陣的每乙個位置,你需要對於這個位置上的值反轉,然後求出這個矩陣的秩的變化 0 可以將這個矩陣看成 n 個大小為 0,2 m 的數,秩就是它們線性基的大小。n,m leq 1000 解法 我們判斷求出原先的 n 個向量在原來的線性基中是可以...
省選集訓2022 模擬賽11
題目描述 n 個城市構成一棵樹,現在要求在一些城市中設定監測點,使得每個城市可以通過到監測點的距離區分出來 不同可以知道是到哪個監測點的距離,可以模擬為樹上的座標 給定 q 次修改,每次斷開邊 u,v 再連上邊 x,y 然後求出最小設定的監測點數目。解法 無根樹問題考慮定根,我們先列舉根強制根選取,...