Monitor CodeForces

题目

题意:有一个n*m的显示屏,有q个坏点先后出现,已知第i个坏点位置为(xi,yi),在ti时间出现。显示屏上出现一个k*k的矩阵全都是坏点时显示屏就是坏的。输出显示屏坏的时间,如果不会坏就输出-1。

所以说,O(nmq)到底是怎么过的?

 1 //b[i][j]表示第i行第j个开始的向右延伸的坏条长度
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 struct Point
 6 {
 7     int x,y,t;
 8     bool operator<(const Point& b) const
 9     {
10         return t<b.t;
11     }
12 }p[255000];
13 int b[510][510];
14 bool c[510][510];
15 int n,m,k,q;
16 bool judge(int x,int y)
17 {
18     int i,ans=0;
19     for(i=x;i<=n;i++)
20     {
21         if(b[i][y]<k)
22             break;
23         ans++;
24         if(ans>=k)    break;
25     }
26     for(i=x-1;i>=1;i--)
27     {
28         if(b[i][y]<k)
29             break;
30         ans++;
31         if(ans>=k)    break;
32     }
33     if(ans>=k)
34         return true;
35     else
36         return false;
37 }
38 int main()
39 {
40     int i,j;
41     bool boo;
42     scanf("%d%d%d%d",&n,&m,&k,&q);
43     for(i=1;i<=q;i++)
44         scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].t);
45     sort(p+1,p+q+1);
46     for(i=1;i<=q;i++)
47     {
48         int& x=p[i].x;
49         int& y=p[i].y;
50         c[x][y]=true;
51         for(j=y;j>=1;j--)
52         {
53             if(!c[x][j])    break;
54             b[x][j]=b[x][j+1]+1;
55             if(b[x][j]>=k)
56             {
57                 boo=judge(x,j);
58                 if(boo==true)
59                 {
60                     printf("%d",p[i].t);
61                     return 0;
62                 }
63             }
64         }
65     }
66     printf("-1");
67     return 0;
68 }

 所以,以下才是正解...

正解1:二分时间,把当前时间的显示屏状态求出来并放入二维线段树/树状数组(坏点为1,好点为0),暴力枚举k*k矩阵的右下角端点,看是否某个矩阵的所有点的和为k*k,如果这样就说明这一块全坏了。

正解2:每个格子记录变坏的时间(不坏的就给个大值),放进二维线段树,然后暴力查询每个k*k的矩阵中变坏时间的最大值,再取所有最大值的最小值,就是答案(如果为那个大值就是-1)

原文地址:https://www.cnblogs.com/hehe54321/p/cf-846d.html