JZOJ 5938. 【NOIP2018模拟10.30】分离计划
Description
眾所周知,小Z擁有者足以毀滅世界的力量,可惜他不能控制這份力量,小J和小Z的關系十分親密,一天小J預感到了小Z體內的力量將要爆發(fā)。
這次爆發(fā)的力量比以往都要強大,以至于將小Z分為了兩個整體,彼此之間靠著萬有引力互相靠近,一旦融合,世界將不復存在。
為了拯救世界,小J決定打造一個容器G,將小Z的兩個部分分別裝在容器G的一個部分,用以控制小Z
容器由n*m個魔法水晶組成,他們組成了一個n行m列的矩陣,每個魔法水晶都有自己的能量值,容器需要
被分為兩個部分,使得每個魔法水晶都屬于且僅屬于一個部分,并且任何一個魔法水晶都可以在矩陣中只經(jīng)過和自己屬于同一部分的魔法水晶由一條最多改變一次方向的路徑抵達另一個和他處于同一部分的魔法水晶
例如:
AAAAA. .AAAAA. .AAAAA
AABAA. .BAAAA. .AAABB
ABBBA. .BBAAA. .AAABB
AABAA. .BAAAA. .ABBBB
AAAAA. .AAAAA. .BBBBB
…(1)…(2)…(3)…
使用.隔開(辣雞的題面格式化)
其中12是不合法的容器,3是合法的容器
對于每一個部分,他的不穩(wěn)定性是屬于這個部分的所有魔法水晶能量值的極差(最大-最小)
對于整個容器,不穩(wěn)定性是兩部分不穩(wěn)定性中的最大值
為了知道自己能不能拯救世界,不白白浪費時間,小J想知道整個容器的最小的不穩(wěn)定值
Input
第一行兩個數(shù)n,m代表魔法水晶組成的矩陣大小
隨后n行,每行m個整數(shù)表示魔法水晶的能量值
Output
一行一個整數(shù),表示最小的不穩(wěn)定值
Sample Input
4 4
1 12 6 11
11 4 2 14
10 1 9 20
4 17 13 10
Sample Output
11
樣例說明
BBBA
BBBA
BBBA
BAAA
B極差12-1=11 A極差20-10=10,不穩(wěn)定值為11,分法不唯一
Data Constraint
對于15%的數(shù)據(jù) n,m≤10
對于另15%的數(shù)據(jù),n,m中有一個為1
對于55%的數(shù)據(jù) n,m≤200(包括最初的15%)
對于所有數(shù)據(jù),n,m≤2000,1≤能量值≤1e9
Solution
-
首先要發(fā)現(xiàn)分成的兩部分一定是一個階梯狀。
-
設矩陣中最大值為 mxmxmx 、最小值為 mnmnmn。
-
那答案最大也就是 mx?mnmx-mnmx?mn ,如果更小的話,那么就將會是 mxmxmx 在一部分, mnmnmn 在另一部分。
-
這里只考慮令階梯型從左下到右上(將原矩形旋轉90°,轉四次處理取最小值即可)的情況。
-
我們強制令 mxmxmx 在左上部分、mnmnmn 在右下部分(沒有也沒關系,反正轉四次總會有的)。
-
再二分答案 midmidmid ,那么每一行從左開始的值都會有一個限制(即值不能小于 mx?midmx-midmx?mid)。
-
這個我們可以對每一行做一個前綴最小值,二分出那個位置 pospospos 即可。
-
之后我們就要判斷 pospospos 之后的值是否也滿足條件(即值不能超過 mn+midmn+midmn+mid)。
-
這個我們可以對每一行做一個后綴最大值,直接判斷即可。
-
時間復雜度就是 O(4(nm+nlog2n))O(4(nm+n\ log^2n))O(4(nm+n?log2n)) 。
Code
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> using namespace std; const int N=2005,inf=1e9; int n,m,ans=inf,mn=inf,mx; int a[N][N],b[N][N]; int pre[N][N],suf[N][N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline int max(int x,int y) {return x>y?x:y; } inline int min(int x,int y) {return x<y?x:y; } inline bool check(int x) {int last=m+1;for(int i=1;i<=n;i++){int l=0,r=m,pos=0;while(l<=r){int mid=l+r>>1;if(mx-pre[i][mid]<=x){l=mid+1;pos=mid;}else r=mid-1;}last=min(last,pos);if(suf[i][last+1]-mn>x) return false;}return true; } inline void work() {for(int i=1;i<=n;i++){pre[i][0]=inf;for(int j=1;j<=m;j++) pre[i][j]=min(pre[i][j-1],a[i][j]);suf[i][m+1]=0;for(int j=m;j;j--) suf[i][j]=max(suf[i][j+1],a[i][j]);}int l=0,r=mx-mn,val=r;while(l<=r){int mid=l+r>>1;if(check(mid)){r=mid-1;val=mid;}else l=mid+1;}ans=min(ans,val); } int main() {freopen("separate.in","r",stdin);freopen("separate.out","w",stdout);n=read(),m=read();for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){a[i][j]=read();mn=min(mn,a[i][j]);mx=max(mx,a[i][j]);}work();for(int i=2;i<=4;i++){for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) b[j][n-i+1]=a[i][j];memcpy(a,b,sizeof(a));swap(n,m);work();}printf("%d",ans);return 0; }總結
以上是生活随笔為你收集整理的JZOJ 5938. 【NOIP2018模拟10.30】分离计划的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 5931. 【NOIP2018
- 下一篇: JZOJ 5939. 【NOIP2018