很長時間沒有考過試了所以今天很激動
且考完試改完題不想做題所以過來寫博客虛度光陰QAQ
傳送門(校內)
題目大意
有 個數,以及一個的矩陣。現在從個數中取出個,並填入這個矩陣中。矩陣每一行的值被定義爲本行最大值與最小值的差,而整個矩陣的值被定義爲爲每一行的值的最大值。求矩陣的最小值。
1≤R,C≤104,R∗C≤N≤5∗105,0<pi≤109
部分分解法(比如說50分)
那麼考場上我的第一想法是DP(裝作看不見數據範圍
首先把整個序列從小到大排序,很容易發現最後的答案一定是連續的某幾段(感性認識即可,證明好像也不難)
那麼我們就考慮從這一個序列中挑出連續的段,每段個數,使得每一行的最小值最小。
那麼我們用 從第i個數開始選擇k個數的極差
用表示選擇從第個開始的個數,已經選了組這樣的數。
(我就是在這裏犯了傻,看了眼數據範圍,拿最大值一除,以爲這個只有五十多)
很快能得到轉移方程 =,其中K要遍歷 ~
考慮到這樣的話複雜度是N^2,明顯過不了,然後發現我們的是從1~N的,所以再記一個來表示
在1~i 的範圍內,選 j 組數的最優方案的結果。
=
大功告成,如果我們把 j 當成50,這個算法的複雜度就是
然後我滿心歡喜的覺得自己過了
正解
其實,我剛纔扯那麼多半點用沒有。
你以爲這是個DP題?不你錯了,這就是個**二分題而已。
我們二分答案,每次跑一遍,複雜度
大功告成,上代碼:
#include<bits/stdc++.h>
#define rint register int
#define ivoid inline void
#define iint inline int
#define endll '\n'
#define ll long long
using namespace std;
const int N=5e5+5;
const int M=3e3+5;
const int inf=0x3f3f3f3f;
int n,m,u,v,w,x,y,z;
int a[N],sum,tot,res,l,r,mx,my,ans,num;
iint rad()
{
int x=0,f=1;char c;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x*f;
}
iint check(int s)
{
int x1=a[1],tot=0;
int l=1;
while(l+y-1<=n){
if(a[l+y-1]-a[l]>s)l++;
else tot++,l=l+y;
}
return tot;
}
int main()
{
n=rad();x=rad();y=rad();
for(rint i=1;i<=n;i++)a[i]=rad();
sort(a+1,a+n+1);
int l=1,r=a[n],mid,ans=inf,t=0;
while(l<r){
mid=(l+r)>>1;
t=check(mid);
if(t<x)l=mid+1;
else ans=mid,r=mid;
}
cout<<ans;
}
總結
之所以我做錯了還要把做錯的方法放上來,emm
是因爲貌似這種解法適用於另一類題??反正我就是覺得這DP思路挺正,如果不是因爲那個神奇的 j 我多半就可以過了對吧(瘋狂找藉口
總之,做題的時候一定一定不要想太多,能簡單做就簡單做,想多了不但會出事,而且還過不了QAQ