1. 程式人生 > >省賽選拔-單調佇列

省賽選拔-單調佇列

單調佇列寫法。

Py&hyh想脫單

Description

總所周知,pyhyh有十分濃烈的脫單意願,但是非常不幸,在一個風和日麗的下午,他們穿越到一個沒有妹子的世界,他必須回答一個問題才能回到本來的世界,這個問題是給出一個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這個時刻,xiyi這個位置會被摧毀

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;
}