POJ 2029 Get Many Persimmon Trees (二维树状数组 or DP)

题意:一个H * W的大矩形,里面的某些格子种有树。现在要你找出一个h * w的小矩形,使得里面树的数量最多,问最多有多少棵树

是二维树状数组基础用法,边输入边更新有树的点,建完树后就可以查询每个(1,1)到(x,y)为对顶点的矩形中共有多少棵柿子树。

算法复杂度 O(H*W*lgH*lgW)

但是由于这题的柿子树一旦确定位置后就没有更新位置,所以不需要用树状数组也可,直接用dp统计每个(1,1)到(x,y)为对顶点的矩形中共有多少棵柿子树。

统计的状态转移方程是:

for(int i=1;i<=hig;i++)

for(int j=1;j<=wid;j++)

dp[i][j]=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1]+dp[i][j];

总算法复杂度是O(H*W)比用树状数组更优

树状数组代码:

//180K	16MS
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define M 100+10
int tree[M][M];
int m,wid,hig;
int lowbit(int x){return x&-x;}

void update(int x,int y)
{
    while(y<=hig){
        int tmp=x;
        while(tmp<=wid){
            tree[y][tmp]++;
            tmp+=lowbit(tmp);
        }
        y+=lowbit(y);
    }
}
int query(int x,int y)
{
    int s=0;
    while(y>0){
        int tmp=x;
        while(tmp>0){
            s+=tree[y][tmp];
            tmp-=lowbit(tmp);
        }
        y-=lowbit(y);
    }
    return s;
}
int main()
{
    while(scanf("%d",&m),m){
        memset(tree,0,sizeof(tree));
        scanf("%d%d",&wid,&hig);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            update(x,y);
        }
        int w,h;
        scanf("%d%d",&w,&h);
        int ans=-1;
        for(int i=1;i<=hig;i++)
        for(int j=1;j<=wid;j++){
            if(j+w-1>wid||i+h-1>hig) continue;
            int cnt= query(j+w-1,i+h-1)-query(j+w-1,i-1)-query(j-1,i+h-1)+query(j-1,i-1);
            ans=max(ans,cnt);
        }
        printf("%d\n",ans);
    }
    return 0;
}

DP代码:

//180K	0MS
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define M 100+10
int dp[M][M];
int m,wid,hig;
int main()
{
    while(scanf("%d",&m),m){
        memset(dp,0,sizeof(dp));
        scanf("%d%d",&wid,&hig);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            dp[y][x]=1;
        }
        for(int i=1;i<=hig;i++)
        for(int j=1;j<=wid;j++)
            dp[i][j]=dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1]+dp[i][j];

        int w,h;
        scanf("%d%d",&w,&h);
        int ans=-1;
        for(int i=1;i<=hig;i++)
        for(int j=1;j<=wid;j++){
            if(j+w-1>wid||i+h-1>hig) continue;
            int cnt= dp[i+h-1][j+w-1]-dp[i+h-1][j-1]-dp[i-1][j+w-1]+dp[i-1][j-1];
            ans=max(ans,cnt);
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-03 22:56:45

POJ 2029 Get Many Persimmon Trees (二维树状数组 or DP)的相关文章

POJ2029:Get Many Persimmon Trees(二维树状数组)

Description Seiji Hayashi had been a professor of the Nisshinkan Samurai School in the domain of Aizu for a long time in the 18th century. In order to reward him for his meritorious career in education, Katanobu Matsudaira, the lord of the domain of

poj 2155 二进制0 1反转---二维树状数组

http://poj.org/problem?id=2155 上午自己搞了很久胡思乱想了很久,然后没思路-----看了论文<浅谈信息学竞赛中的"0"和"1"--二进制思想在信息学竞赛中的应用>,豁然开朗啊,,马上A掉---PE了一次o(╯□╰)o 通过论文学到的两点: 1.多维不会的时候,从一维尝试类比: 2.想法的证明,情况数不多的时候,分类讨论证明很好 #include <cstdio> #include <cstring>

[BZOJ3594] [Scoi2014]方伯伯的玉米田 二维树状数组优化dp

我们发现任何最优解都可以是所有拔高的右端点是n,然后如果我们确定了一段序列前缀的结尾和在此之前用过的拔高我们就可以直接取最大值了然后我们在这上面转移就可以了,然后最优解用二维树状数组维护就行了 #include<cstdio> #include<cstring> #include<algorithm> #define N 10005 #define K 505 #define M 5505 using namespace std; inline int read() {

[SCOI2014]方伯伯的玉米田 //二维树状数组优化DP//unfinished

闲的慌,从HZOJ里挑了道DP题来做,没想到这么恐怖 但是已经开了坑也不能退,干脆写吧 题目: 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把这个区间的玉米全部拔高1单位高度,他可以进行最多K次这样的操作.拔玉米则可以随意选择一个集合的玉米拔掉.问能最多剩多少株玉米,来构成一排美丽的玉米

[poj2155]Matrix(二维树状数组)

Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 25004   Accepted: 9261 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1

POJ 2029 Get Many Persimmon Trees (二维树状数组)

Get Many Persimmon Trees Time Limit:1000MS    Memory Limit:30000KB    64bit IO Format:%I64d & %I64u SubmitStatusPracticePOJ 2029 Description Seiji Hayashi had been a professor of the Nisshinkan Samurai School in the domain of Aizu for a long time in

Get Many Persimmon Trees_枚举&amp;&amp;二维树状数组

Description Seiji Hayashi had been a professor of the Nisshinkan Samurai School in the domain of Aizu for a long time in the 18th century. In order to reward him for his meritorious career in education, Katanobu Matsudaira, the lord of the domain of

POJ 1195 Mobile phones(二维树状数组)

题目链接:POJ 1195 题意: 给出一个S*S的矩阵(行.列号从1开始),每个元素初始值为0,有两种操作:一种是第X行第Y列元素值加A:另一种是查询给定范围矩阵的所有元素之和(L<=X<=R,B<=Y<=T). 分析: 查询给定范围矩阵的所有元素之和是二维区间和,可以转换为二维前缀和求值.类比一维前缀和求法,二维区间和S(L, B, R, T) = S(1, 1, R, T) - S(1 ,1, L-1, T) - S(1, 1, R, B-1) + S(1, 1, L-1,

POJ 2155 Matrix(二维树状数组,绝对具体)

Matrix Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 20599   Accepted: 7673 Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row and j-th column. Initially we have A[i, j] = 0 (1