目录
题意:
给出n*m的矩阵,k次查询,如果至少有一列从第l行到r行是非递减的,则输出Yes,否则输出No
数据范围:
(1 ≤ n·m ≤ 100 000)
(1 ≤ ai, j ≤ 109)
(1 ≤ k ≤ 100 000)
(1 ≤ li ≤ ri ≤ n).
思路分析:
根据数据范围,暴力和开二维数组不适用。可以用一个数组a[i]表示第i列的位置到a[i]列组成的区间[a[i],i]是非递减的。
输入过程中以行输入。所以用c[j]维护目前最新的第j列对应的数。b[j]表示目前第j列维护的非递减区间的开头。这样如果出现输入的x比c[j]小,那么就证明这一列在这里出现了递减,这时候更新b[j]=i。每次都要更新a[i]=min(a[i],b[j])。初始化a[i]=i。可能把a换成dp更好理解,稍微有点动态规划的思想。
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e5+50;
int a[maxn];//a[i]代表从i行开始可以找到最小的a[i],使得 [a[i],i]非递减
int b[maxn];//b[j]目前第j列非递减开头的值
int c[maxn];//更新每次对应列的输入值c[j]目前第j列最新的值
int main(){
int n,m,x;
cin >> n >> m;
for(int i = 1;i <= n;i++){
a[i] = i;
for(int j = 1;j <= m;j++){
cin >> x;
if(x < c[j]) b[j] = i;
c[j] = x;
if(a[i] > b[j]) a[i] = b[j];
}
}
int k,l,r;
cin >> k;
while(k--){
cin >> l >> r;
if(a[r] <= l) cout<<"Yes"<<endl;
else cout<<"No\n";
}
return 0;
}