zoukankan      html  css  js  c++  java
  • CF1598EStaircases【计数】

    正题

    题目链接:https://www.luogu.com.cn/problem/CF1598E


    题目大意

    给出一个\(n\times m\)的网格图,开始所有都是黑色的,\(q\)次取反一个格子的颜色,然后求楼梯的数量。

    楼梯定义为全黑色的下/右交替的格子集。

    \(1\leq n,m\leq 1000,1\leq q\leq 10^4\)


    解题思路

    注意到其实是两个斜行交错,可以考虑把坐标轴旋转\(45°\),然后发现其实就是相邻的两行的正方形数量。

    \(f_{i,j}\)表示格子\((i,j)\)所在斜行再往\((i,j)\)左上角的能延伸多少个黑色,然后每次\(O(n)\)暴力修改即可。

    时间复杂度:\(O(qn)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=1100;
    ll n,m,q,w[N][N],a[N][N],ans;
    ll calc(ll x,ll y)
    {
    	if(y<0)return 0;
    	return min(x,y+1)+min(x,y);
    }
    signed main()
    {
    	scanf("%lld%lld%lld",&n,&m,&q);
    	for(ll i=1;i<=n;i++)	
    		for(ll j=1;j<=m;j++)
    			w[i][j]=w[i-1][j-1]+1;
    	for(ll i=1;i<=n;i++)
    		for(ll j=1;j<=m;j++)
    			ans+=calc(w[i][j],w[i-1][j])+calc(w[i][j],w[i][j-1])-1;
    	while(q--){
    		ll x,y;
    		scanf("%lld%lld",&x,&y);
    		if(a[x][y]){
    			ll dx=x,dy=y;x++;y++;
    			while(x<=n&&y<=m&&!a[x][y]){
    				ans-=calc(w[x][y],w[x-1][y])+calc(w[x][y],w[x][y-1])-1;
    				ans-=calc(w[x][y],w[x+1][y]-1)+calc(w[x][y],w[x][y+1]-1);
    				x++;y++;
    			}
    			x=dx;y=dy;a[x][y]^=1;
    			while(x<=n&&y<=m&&!a[x][y])
    				w[x][y]=w[x-1][y-1]+1,x++,y++;
    			x=dx;y=dy;
    			while(x<=n&&y<=m&&!a[x][y]){
    				ans+=calc(w[x][y],w[x-1][y])+calc(w[x][y],w[x][y-1])-1;
    				ans+=calc(w[x][y],w[x+1][y]-1)+calc(w[x][y],w[x][y+1]-1);
    				x++;y++;
    			}
    		}
    		else{
    			ll dx=x,dy=y;
    			while(x<=n&&y<=m&&!a[x][y]){
    				ans-=calc(w[x][y],w[x-1][y])+calc(w[x][y],w[x][y-1])-1;
    				ans-=calc(w[x][y],w[x+1][y]-1)+calc(w[x][y],w[x][y+1]-1);
    				x++;y++;
    			}
    			x=dx;y=dy;a[x][y]^=1;w[x][y]=0;x++;y++;
    			while(x<=n&&y<=m&&!a[x][y])
    				w[x][y]=w[x-1][y-1]+1,x++,y++;
    			x=dx;y=dy;x++;y++;
    			while(x<=n&&y<=m&&!a[x][y]){
    				ans+=calc(w[x][y],w[x-1][y])+calc(w[x][y],w[x][y-1])-1;
    				ans+=calc(w[x][y],w[x+1][y]-1)+calc(w[x][y],w[x][y+1]-1);
    				x++;y++;
    			}
    		}
    		printf("%lld\n",ans);
    	}
    }
    
  • 相关阅读:
    字符串指针与字符数组的区别
    为什么stc15的单片机,运行了几秒后就蹦了
    判断一个数是否是2的整数次幂
    Ubuntu下使用gcc编译c文件,未识别cos,sin
    数字图像基本处理算法
    开发板启动时,内核打印出"can't access tty,job control turned off"
    c语言里如何调用汇编里的变量?
    leetcode516 Longest Palindromic Subsequence
    leetcode523 Continuous Subarray Sum
    leetcode650 2 Keys Keyboard
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15455820.html
Copyright © 2011-2022 走看看