zoukankan      html  css  js  c++  java
  • HDU 5110 Alexandra and COS

    比赛的时候看完就get到是dp,然后发现要开1000*1000*1000的数组,然后就跪那里起不来了。。。

    赛后看题解学会了一种好机智的姿势啊,将第一维降为√1000,对于D小于√m的用dp做,D大于√m的暴力,这样两种做法都是n^2.5,太机智了。

    psum是前缀和,xpsum[k][i][j]是D为k时,第i行前j列,i-k行前j+k列,i-2k行前j+2k列...的和,f是答案。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    char str[1010];
    int psum[1010][1010],xpsum[40][1010][1010],f[40][1010][1010];
    
    int main()
    {
        int n,m,q;
        int x,y,d;
        int ans;
        while(scanf("%d%d%d",&n,&m,&q)==3) {
            for(int i=1;i<=n;++i) {
                scanf("%s",str+1);
                psum[i][0]=0;
                for(int j=1;j<=m;++j) {
                    psum[i][j]=psum[i][j-1]+(str[j]=='X');
                }
            }
            int B=sqrt(n+0.0);
            for(int k=1;k<=B;++k) {
                for(int i=1;i<=n;++i) {
                    for(int j=1;j<=m;++j) {
                        f[k][i][j]=0;
                        xpsum[k][i][j]=psum[i][j];
                        if(i-k>0) {
                            if(j+k<=m) xpsum[k][i][j]+=xpsum[k][i-k][j+k];
                            else xpsum[k][i][j]+=xpsum[k][i-k][m];
                            if(j-k>0) {
                                f[k][i][j]=f[k][i-k][j-k];
                                f[k][i][j]-=xpsum[k][i-k][j-k];
                                if(j+k<=m) f[k][i][j]+=xpsum[k][i-k][j+k];
                                else f[k][i][j]+=xpsum[k][i-k][m];
                            }
                            else {
                                if(j+k<=m) f[k][i][j]=xpsum[k][i-k][j+k];
                                else f[k][i][j]=xpsum[k][i-k][m];
                            }
                        }
                        f[k][i][j]+=psum[i][j]-psum[i][j-1];
                    }
                }
            }
            while(q--) {
                scanf("%d%d%d",&x,&y,&d);
                ans=0;
                if(d>B) {
                    for(int i=x;i>0;i-=d) {
                        int l=max(1,y-x+i),r=min(m,y+x-i);
                        ans+=psum[i][r]-psum[i][l-1];
                    }
                }
                else {
                    ans=f[d][x][y];
                }
                printf("%d
    ",ans);
            }
        }
    }
  • 相关阅读:
    ThreadLocal
    mysql查看和修改密码策略
    synchronized双重校验问题
    多线程下双重检查锁的问题及解决方法
    compiler explorer网站
    隐藏表格部分内容,开启宏自动显现
    powershell系列学习笔记二:变量
    强制用户启用宏
    poweshell系列学习笔记一:基础
    Cobalt Strike修改证书
  • 原文地址:https://www.cnblogs.com/morimiya/p/4117406.html
Copyright © 2011-2022 走看看