Codeforces 777C Alyona and Spreadsheet
题目链接
http://codeforces.com/problemset/problem/777/C
题目大意
给你一个矩阵,多次询问,每次询问 $L$ 和 $R$ ,你需要回答是否存在一列使得L行到R行为不下降序列
题目分析
这题注意到,只要知道 $L$ 行开始,最长不下降序列最长的那列到哪个位置结束就行了,所以可以先预处理找到所有的不下降序列,就可以找到所有的以某行为起始的最长的不下降序列长度,又因为从前面几行延伸过来的其实也是不下降的,所以再求某一行结束位置和前面几行相比的最大值,查询时比较最大结束位置和 $R$ 谁大就可以了。
代码
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> using namespace std; int n, m; int a[100005]; struct ex { int x; int y; }; ex f[100005]; int cnt = 0; int v[100005]; int t, k; int l, r; int geta(int x, int y){ return a[(x - 1) * m + y]; } int init(){ int i, j; for(i=1;i<=m;i++){ l = 1; for(j=2;j<=n;j++){ if(geta(j, i) < geta(j - 1, i)){ cnt++; f[cnt].x = l; f[cnt].y = j - 1; l = j; } } cnt++; f[cnt].x = l; f[cnt].y = n; } for(i=1;i<=cnt;i++){ v[f[i].x] = max(v[f[i].x], f[i].y); } for(i=1;i<=n;i++){ v[i] = max(v[i], v[i - 1]); } return 0; } bool query(int x, int y){ if(v[x] >= y){ return true; }else{ return false; } } int main(){ int i, j; scanf("%d", &n); scanf("%d", &m); t = n * m; for(i=1;i<=t;i++){ scanf("%d", &a[i]); } init(); scanf("%d", &k); for(i=1;i<=k;i++){ scanf("%d", &l); scanf("%d", &r); if(l == r){ printf("Yes\n"); }else if(query(l, r)){ printf("Yes\n"); }else{ printf("No\n"); } } return 0; }