Monitor CodeForces - 846D
题意:有一个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)