省賽選拔-單調佇列
單調佇列寫法。
Py&hyh想脫單
Description
總所周知,,py和hyh有十分濃烈的脫單意願,但是非常不幸,在一個風和日麗的下午,他們穿越到一個沒有妹子的世界,他必須回答一個問題才能回到本來的世界,這個問題是給出一個nm的矩陣,然後有q次操作,每一個操作,給出xi,yi,ti,表示在ti時刻摧毀(xi,yi)這個格子,然後他們要求出一個最早時刻,出現至少一個kk的矩陣被毀壞,注意:一個kk矩陣被毀壞的意思是某一個kk的矩陣中的每一個格子都被摧毀過一次或一次以上。聰明的acmer能幫他們回答這個問題嗎(如果沒人能ac這個題,就代表他們兩個沒有脫單的可能了哦)
Input
Input:採用多組輸入第一行輸入n,m,k,q,(1 ≤ n, m ≤ 500, 1 ≤ k ≤ min(n, m), 1 ≤ q ≤ n·m)分別代表nm的矩陣,kk的矩陣,和q次操作接下來q行每一行輸入xi,yi,ti(1 ≤ xi ≤ n, 1 ≤ yi ≤ m, 0 ≤ t ≤ 1e6),代表,在ti這個時刻,xi,yi這個位置會被摧毀
Output
Out:輸出一行,代表最早時刻出現至少一個k*k的矩陣被毀壞如果永遠不存在這一個時刻,輸出-1
Sample Input 1
2 3 2 5
2 1 8
2 2 8
1 2 1
1 3 4
2 3 2
Sample Output 1
8
Sample Input 2
3 3 2 5
1 2 2
2 2 1
2 3 5
3 2 10
2 1 100
Sample Output 2
-1
題意:自己看。
解法:標程是二分+二維字首和,我個人覺得雙向佇列寫法更優。
首先每行 記錄 mp[i][ j-k , j ]區間的最大值,再在得到每行每個區間最大值的條件下再次記錄 每列的最大值 mp[i-k,i][j];
這中寫法只要會用雙向佇列來維護單調佇列,就很好些。
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cmath> #include<queue> #include<map> #include<set> #include<stack> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> P; #define bug printf("*********\n"); #define debug(x) cout<<"["<<x<<"]" <<endl; #define mid (l+r)/2 #define chl 2*k+1 #define chr 2*k+2 #define lson l,mid,chl #define rson mid,r,chr #define pb push_back const long long mod=998244353; const int maxn=5e3+5; const int INF=0x7fffffff; const int inf=0x3f3f3f3f; const double eps=1e-8; int n,m,k,q; deque<int> dq; int mp[maxn][maxn]; int mp2[maxn][maxn]; //開個mp2記錄下每行一個區間的最大值 int main() { while(~scanf("%d%d%d%d",&n,&m,&k,&q)) { memset(mp,inf,sizeof(mp)); while(q--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); mp[a][b]=min(mp[a][b],c); } for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(j>k&&dq.back()==mp[i][j-k]) { dq.pop_back(); } while(dq.size()>0&&dq.front()<mp[i][j]) { dq.pop_front(); } if(dq.size()==0||dq.front()>=mp[i][j]) { dq.push_front(mp[i][j]); } mp2[i][j]=dq.back(); } dq.clear(); } for(int i=k; i<=m; i++) { for(int j=1; j<=n; j++) { if(j>k&&dq.back()==mp2[j-k][i]) { dq.pop_back(); } while(dq.size()>0&&dq.front()<mp2[j][i]) { dq.pop_front(); } if(dq.size()==0||dq.front()>=mp2[j][i]) { dq.push_front(mp2[j][i]); } mp[j][i]=dq.back(); } dq.clear(); } int res=inf; for(int i=k; i<=n; i++) { for(int j=k; j<=m; j++) { res=min(res,mp[i][j]); } } if(res>1e6+1)res=-1; printf("%d\n",res); } return 0; }