zoukankan      html  css  js  c++  java
  • 前缀和

    前缀和这种小技巧noip很容易就考到了,例如11年的聪明的质监员这道题二分但是用到了前缀和优化。前缀和可以优化一下时间复杂度。

    首先是一维的前缀和,a[i]+=a[i-1];这样很简单使用的时候只要直接a[r]-a[l-1]就可以吧r到l直接的累加全部搞出来优化一重循环0.0;

    下面是10.21考的普及组的一道题,一眼看出是个二维的前缀和,但下手的时候由于时间不充足还是选择打了暴力结果GG。

    范围n,m<=300,显然二维的前缀和只要数出0和1的个数即可,不会啊~~~。

    这个要怎么求呢?很显然当前的值a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1]即可这样前缀和就解决了,但是如何调用也是一个问题。

    当前是要求每个小矩阵的0和1所以当前的点是向外延伸k的长度的所以可设当前点为i,j矩阵右下方的端点为w=i+k-1,y=j+k-1(注意细节),那么只要求出来从w,y到i,j直接的0和1的个数即可。自己画个图易知当前前缀和=a[w][y]-a[w][j-1]+a[i-1][y]+a[i-1][j-1].这样问题就被完美的解决了,这道题有很多的细节,码力不好的话很容易就wa掉。。。见代码:

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<vector>
    #include<map>
    #include<queue>
    #include<iomanip>
    #include<stack>
    #include<algorithm>
    using namespace std;
    inline long long read()
    {
        long long x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const long long maxn=1000;
    long long n,m;
    long long a[maxn][maxn],ans=0,ans1=0,tot=0,s;
    struct bwy{long long x,y;}b[maxn][maxn];
    int main()
    {
        //freopen("paint.in","r",stdin);
        //freopen("paint.out","w",stdout);
        //freopen("1.in","r",stdin);
        n=read();m=read();s=min(n,m);
        for(long long i=1;i<=n;i++)
        {
            for(long long j=1;j<=m;j++)
            {    
                a[i][j]=read();
                if(a[i][j]==1)
                {
                    b[i][j].x++;
                    b[i][j].x+=b[i][j-1].x;
                    b[i][j].x+=b[i-1][j].x-b[i-1][j-1].x;
                    b[i][j].y+=b[i][j-1].y;
                    b[i][j].y+=b[i-1][j].y-b[i-1][j-1].y;
                }
                else
                {
                    b[i][j].y++;
                    b[i][j].x+=b[i][j-1].x;
                    b[i][j].x+=b[i-1][j].x-b[i-1][j-1].x;
                    b[i][j].y+=b[i][j-1].y;
                    b[i][j].y+=b[i-1][j].y-b[i-1][j-1].y;
                }
            }    
        }
        //for(long long i=1;i<=n;i++){for(long long j=1;j<=m;j++){printf("%d ",b[i][j].x);}printf("
    ");}
        for(long long k=2;k<=s;k++)
        for(long long i=1;i<=n-k+1;i++)
        {
            for(long long j=1;j<=m-k+1;j++)
            {
                long long w=i+k-1,y=j+k-1;
                if(abs((b[w][y].x+b[i-1][j-1].x-b[w][j-1].x-b[i-1][y].x)-(b[w][y].y+b[i-1][j-1].y-b[w][j-1].y-b[i-1][y].y))<=1)
                    tot++;
            }
        }
        printf("%lld
    ",tot);
        return    0;
    }
    View Code

    此其所挟持者甚大,而其志甚远也。

  • 相关阅读:
    NX二次开发-UFUN指定原点和轴旋转视图UF_VIEW_rotate_view_abs_csys
    NX二次开发-将草图直线约束到基准轴上SketchConstraintBuilder
    NX二次开发-UFUN检验两条直线几何上是否不同UF_CURVE_LINE_ARC__is_line_equal
    C++封装DLL文件并且调用
    NX二次开发-C# NXOPEN方式多选对话框theUI.SelectionManager.SelectTaggedObjects
    NX二次开发-NXOPEN C# Part.GetPreviewImage读取prt文件预览图
    PythonOCC开发-如何搭建开发环境和一个创建圆台例子
    NX二次开发-C# NXOPEN方式单选对话框UI.GetUI().SelectionManager.SelectTaggedObject
    羊城通薅羊毛6折公交算法
    Windows DOS命令微信多开
  • 原文地址:https://www.cnblogs.com/chdy/p/9832441.html
Copyright © 2011-2022 走看看