CodeForces - 777C Alyona and Spreadsheet

题意:

有一个n*m的矩阵,岳老板会给出若干的询问区间[l,r](注意是闭区间),周嘉晨需要回答在1到m这些列中有没有一列满足从第l个数到第r个数是从小到大排序的。有的话输出Yes,没有输出No。。

输入的第一行包含两个正整数 n 和 m (1 ≤ n·m ≤ 100 000) 分别表示矩阵的行和列。 注意数据保证的是两个数的乘积。

接下来的 n 行每行包括 m 个数. 第 i行中第j个数为ai, j (1 ≤ ai, j ≤ 109).

接下来的一行包含一个整数 k (1 ≤ k ≤ 100 000) 表示岳老板给qzh的询问个数

i个询问包含两个整数li 和 ri (1 ≤ li ≤ ri ≤ n).

 

 

题解:看完下面的图片就很清楚了。括号外面的数字是输入给的,括号里面的数字是Begin数组的值。。

Begin数组记录从上到下某个递减序列的首个元素的位置..(记录该元素的行坐标即可)

在第j列,若从第x行到第y行是非递减的的,且x是这个序列的首个数字,就用一个Begin[y][j] = x;  

若a[ i ][ j ] >= a[ i-1][ j ] . Begin[ i ][ j ] = Begin[ i - 1 ] [ j ]

                             否则. Begin[ i ][ j ] = i  

CodeForces - 777C Alyona and Spreadsheet_第1张图片

这样,每次询问 li , ri 的时候,只要有一列的Begin[ li ][ j ] = Begin[ ri ][ j ] ,就可以输出Yes。。

从1到m行枚举就可以得到答案,但这样做会超时。。我们再用一个数组x[ i ] ,另

x[i] = min( Begin[i][j] ) 。。然后每次查询 li , ri 的时候,若x[ ri ] 是否小于等于 li ,

输出Yes。。否则输出No

 

#include
#include
#include
using namespace std;
vector a[100010];
vector Begin[100010];
int x[101000];
int n,m,temp;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<101000;i++) x[i]=i;
    for(int i=1;i<=n;i++){
        for(int j=0;j             scanf("%d",&temp);
            a[i].push_back(temp);
        }
    }
    for(int i=0;i         Begin[1].push_back(1);


    for(int i=2;i<=n;i++){
        for(int j=0;j             if(a[i][j]>=a[i-1][j])
                Begin[i].push_back(Begin[i-1][j]);
            else
                Begin[i].push_back(i);
            x[i] = min(x[i],Begin[i][j]);
        }
        
    }
    
    int  t;
    scanf("%d",&t);
    while(t--){
        int up,down;
        scanf("%d%d",&up,&down);
        if(x[down]<=up)
            printf("Yes\n");
        else
            printf("No\n");
    }
    return 0;
}

你可能感兴趣的:(CodeForces - 777C Alyona and Spreadsheet)