zoukankan      html  css  js  c++  java
  • 【CF627E】Orchestra(链表)

    点此看题面

    大致题意: 给定一个(r imes c)的矩阵,其中有(n)(1)。问有多少子矩阵包含至少(k)(1)

    解题思路

    不得不说这题的思想是非常巧妙的。

    有一个显而易见的(O(r^2c))暴力,即枚举子矩阵上下边界,然后用尺取法(双指针)扫一遍。

    现在我们考虑仍旧枚举上边界,然后从下往上枚举下边界,每次移动下边界时求出删去这一层点给答案带来的变化。

    删去一个点,因此而减少的贡献就是所有包含它所在列且恰好包含(k)个点的矩阵个数。

    我们用链表来维护有点的每一列,那么暴力找出这些矩阵最多也就只要往前跳(k)次,同时维护好右边界即可。

    总复杂度(O(r^2k))

    (P.S.) 写完后发现似乎也可以从上往下枚举下边界,然后加上每一层点的答案?而且这样还不用求初始答案了。。。

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 3000
    #define K 10
    #define LL long long
    using namespace std;
    int r,c,n,k,cnt[N+5],pre[N+5],nxt[N+5],C[N+5],v[N+5][N+5];struct P {int x,y;}p[N+5];
    int main()
    {
    	RI i,j,s,x,y;for(cin>>r>>c>>n>>k,i=1;i<=n;++i) cin>>x>>y,v[x][++C[x]]=y;//记下每一行的点的列号
    	RI t,cur,res;LL ans=0;for(i=1;i<=r;++i)//枚举上边界
    	{
    		for(res=0,j=i;j<=r;++j) for(s=1;s<=C[j];++s) ++cnt[v[j][s]];//枚举所有点计算每一列的点数
    		for(pre[1]=0,j=2;j<=c+1;++j) pre[j]=cnt[j-1]?j-1:pre[j-1];//链表初始化向前指针
    		for(nxt[c]=c+1,j=c-1;~j;--j) nxt[j]=cnt[j+1]?j+1:nxt[j+1];//链表初始化向后指针
    		for(x=nxt[0];x<=c;x=nxt[x])//枚举子矩阵第一个有1的列,计算初始答案
    		{
    			t=0,y=x;W(y<=c&&(t+=cnt[y])<k) y=nxt[y];//暴力向后跳到第一个满足条件的右边界
    			res+=(x-pre[x])*(c-y+1);//统计答案
    		}
    		for(j=r;j>=i;--j) for(ans+=res,s=1;s<=C[j];++s)//从下往上枚举下边界,删去每层点的贡献
    		{
    			if(--cnt[cur=v[j][s]]>=k) continue;//如果这一列的点数仍旧大于等于k,对答案无影响
    			t=0,y=cur;W(y<=c&&(t+=cnt[y])<k-1) y=nxt[y];//暴力向后跳找到初始右边界
    			x=cur;W(x)//枚举左边界
    			{
    				W(y^cur&&t-cnt[y]>=k-1) t-=cnt[y],y=pre[y];if(y==cur&&t>=k) break;//右边界能移就移,若不合法就结束循环
    				t+1==k&&(res-=(x-pre[x])*(nxt[y]-y)),t+=cnt[x=pre[x]];//恰好k个点时从答案中减去贡献,然后移动左边界
    			}
    			!cnt[cur]&&(nxt[pre[cur]]=nxt[cur],pre[nxt[cur]]=pre[cur]);//没点后从链表中删去
    		}
    	}return printf("%lld
    ",ans),0;//输出答案
    }
    
  • 相关阅读:
    yii 引入文件
    CodeForces 621C Wet Shark and Flowers
    面试题题解
    POJ 2251 Dungeon Master
    HDU 5935 Car(模拟)
    HDU 5938 Four Operations(暴力枚举)
    CodeForces 722C Destroying Array(并查集)
    HDU 5547 Sudoku(dfs)
    HDU 5583 Kingdom of Black and White(模拟)
    HDU 5512 Pagodas(等差数列)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF627E.html
Copyright © 2011-2022 走看看