zoukankan      html  css  js  c++  java
  • HDU5110:Alexandra and COS(分块+容斥)

    传送门

    题意

    给出(n*m)的矩阵,'X'代表treasure.(q)个询问,每次询问(x,y)且频率为d的潜艇能探索到多少财富。探索范围要求abs(x1-x)>=abs(y1-y),也就是左斜方/右斜方(45°),而且要求(max(abs(x1-x),abs(y1-y)))为d的倍数

    分析

    本题直接预处理每个点的复杂度为(O(nmn)),会TLE,考虑分块,将(d<sqrt{n})的点进行预处理,复杂度为(O(nmsqrt{n})),其余点直接暴力算,复杂度为(O(sqrt{n})),而预处理的方法我是从sio_five学到的,不同于复杂的状态转移,而,是采用右三角形-左三角形的方法,代码简短,十分精妙

    trick

    1.有一点需要注意,如果数组下标未与循环相对应,会TLE,与ac相差3+s,有claris的说法,未对应导致物理不连续,进而导致寻址慢,以后要注意

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define F(i,a,b) for(int i=a;i<=b;++i)
    #define R(i,a,b) for(int i=a;i<b;++i)
    #define mem(a,b) memset(a,b,sizeof(a))
    const int N = 1010;
    int n,m,q,x,y,d,B;
    int sum[N][N],g[33][N][N],sa[N][33],gl[N][N],gr[N][N];
    //sum[i][j]记录第i行的前j个和,sa[i][j]记录前i行间距为j的行和,比如sa[3][2]=sum[3][m]+sum[1][m]
    //gl[i][j]记录以(i,j)为边界的左三角形,gr[i][j]记录以(i,j)为边界的右三角形
    char s[N][N];
    void init()
    {
        F(i,1,n)F(j,1,B)
        {
            if(i<j) sa[i][j]=sum[i][m];
            else sa[i][j]=sa[i-j][j]+sum[i][m];
        }
        F(k,1,B)F(i,1,n)F(j,1,m)
        {
            //gl
            if(i<=k||j<=k) gl[i][j]=sum[i][j];
            else gl[i][j]=gl[i-k][j-k]+sum[i][j];
            //gr
            if(i<=k) gr[i][j]=sum[i][j];
            else if(j+k>m) gr[i][j]=sa[i-k][k]+sum[i][j];
            else gr[i][j]=gr[i-k][j+k]+sum[i][j];
            //g
            g[k][i][j]=gr[i][j]-gl[i][j-1];
        }
    }
    void solve()
    {
        int ans=0;
        for(int i=x;i>0;i-=d)
        {
            int l=max(1,y-x+i),r=min(m,y+x-i);
            ans+=sum[i][r]-sum[i][l-1];
        }
        printf("%d
    ",ans);
    }
    int main()
    {
        while(scanf("%d %d %d",&n,&m,&q)!=EOF)
        {
            F(i,1,n)
            {
                scanf("%s",s[i]+1);
                F(j,1,m) sum[i][j]=sum[i][j-1]+(s[i][j]=='X');
            }
            B=sqrt(n);
            init();
            while(q--)
            {
                scanf("%d %d %d",&x,&y,&d);
                if(d<=B) printf("%d
    ",g[d][x][y]);
                else solve(); 
            }
        }
        return 0;
    }
    
  • 相关阅读:
    无法删除文件提示找不到指定文件导致文件无法删除的解决方法
    c++多线程编程(三)
    c++多线程编程(二)
    c++多线程编程(一)
    面试中的C++常见问题
    展示组件(Presentational component)和容器组件(Container component)之间有何不同
    如果你创建了类似于下面的 Twitter 元素,那么它相关的类定义是啥样子的?
    React 中 refs 的作用是什么?
    typescript 类(类的定义、继承、修饰符、抽象类)
    typescript 接口 interface
  • 原文地址:https://www.cnblogs.com/chendl111/p/7096477.html
Copyright © 2011-2022 走看看