1. 程式人生 > >趣題[1]

趣題[1]

tps define second body include puts 我們 earch 右上角

趣題[1]

來源

http://www.csie.ntnu.edu.tw/~u91029/Sequence3.html
UVA - 12192

介紹

引入

\(n*m\)的矩陣,每行從左到右遞增,每列從上到下遞增,在矩陣中找數\(x\)出現過的位置。

具體做法可以在這個鏈接ctrl+F[Search in Sorted Matrix: Saddleback Search],復雜度\(O(n+m)\)

想法

現在我們知道了,從這樣的矩陣的右上角走下來可以把矩陣分成兩個部分,左上部分小於\(x\),右下部分大等於\(x\),這樣的想法有什麽用呢?

小小的實戰!

UVA - 12192
題目要求在\(n*m\)

的矩陣中找一個最大的方陣,使得方陣中所有的元素都在區間\([L, R]\)中。\(1<=n,m<=500\) 詢問\(10000\)次。

做法:把矩陣分成兩個部分,左上部分小於\(L\),右下部分大等於\(L\),然後二分方陣的邊長,check時判斷方針的右下角是不是小等於\(R\)就可以啦。復雜度\(O(q*(n+m)*logn)\)

代碼:

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++) #define sz(x) (int)x.size() #define de(x) cout<< #x<<" = "<<x<<endl #define dd(x) cout<< #x<<" = "<<x<<" " typedef long long ll; typedef pair<int, int> pii; typedef vector<int> vi; //------ const
int N=555; int n,m,l,r; int a[N][N]; int gao(int x,int y) { if(a[x][y]>r||a[x][y]<l) return 0; int lo=1,hi=min(n-x+1, m-y+1); int ans=0; while(lo<=hi) { int mid=(lo+hi)>>1; if(a[x+mid-1][y+mid-1]<=r) { ans=mid; lo=mid+1; } else { hi=mid-1; } } return ans; } int solve() { int ans=0; int x=1,y=m; ans=max(ans,gao(x,y)); while(1) { if(y==1||a[x][y-1]<l) { if(x<n) ++x; else break; } else { --y; } ans=max(ans,gao(x,y)); } return ans; } int main() { while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0) break; ///read rep(i,1,n+1) { rep(j,1,m+1) { scanf("%d",&a[i][j]); } } ///solve int q;scanf("%d",&q); while(q--) { scanf("%d%d",&l,&r); printf("%d\n",solve()); } puts("-"); } return 0; }

趣題[1]