ACwing每日一题 3617. 子矩形计数 差分 + 思维 线性复杂度

题目

ACwing每日一题 3617. 子矩形计数 差分 + 思维 线性复杂度_第1张图片

链接

题解思路

一开始只想着暴力做,用滑动矩形去框区域,时间复杂度甚至大于n平方,肯定会超时,另外还没想出处理其他形状的矩形的方法,就看闫总视频解析去了。
ACwing每日一题 3617. 子矩形计数 差分 + 思维 线性复杂度_第2张图片
直接从符合条件的区域出发来拼接矩形,这就是大佬的思维!
然后对能组合成目标矩形的长宽进行枚举,选择一遍,判断另外一边是否合法,然后让对应的长宽的数量相乘累加。

这样的话我们要分别对A B 处理存储有N个连续1的个数的数组。
如果暴力的话复杂度为 N方 ,这里就用到了差分!
当存在一段区间为1时,我们要对这一段的区间都自增,差分就可以更好的处理这个问题!有关差分

让区间的第一位加上目标值,然后让最后一位的后一位减去目标值,再让差分数组累加前一项。

AC代码

#include 
#include 
using namespace std;
int a[40005];
int c1[40005];
int c2[40005];
int b[40005];
void chafen (int w[],int s[],int n )
{
    int j = 0;
    for (int i = 1 ; i <= n ; i++ )
    {
        if (w[i])
        {
            j++;
            s[1]++;
            s[j+1]--;
        }else
            j = 0;
    }
    for (int i = 1 ; i <= n ; i++ )
        s[i] += s[i-1];
}
int main ()
{
    int n,m,le;
    scanf("%d%d%d",&n,&m,&le);
    for (int i = 1 ; i <= n ; i++ )
        scanf("%d",&a[i]);
    for (int i = 1 ; i <= m ; i++ )
        scanf("%d",&b[i]);
    chafen(a,c1,n);
    chafen(b,c2,m);
    long long ans = 0;
    for (int i = 1 ; i <= n ; i++ )
    {
        if ( le % i == 0 )
        {
            int k = le /i ;
            if ( k > m )
                continue;
            ans += c1[i]*c2[k];
        }
    }
    printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(思维,数论,算法)