zoukankan      html  css  js  c++  java
  • Codeforces Round #620 Div2F Animal Observation(前缀和+动态规划+线段树维护)

    题意:

    作者喜欢观察动物,因此他购买了两个照相机,以拍摄森林中野生动物的视频,一台摄像机的颜色是红色,一台摄像机的颜色是蓝色。

    从第1天到第N天,作者将拍摄N天的视频。森林可以分为M个区域,编号从1到M。他将通过以下方式使用相机:

    在每个奇数天,将红色相机带到森林中并录制两天的视频。

    在每个偶数天,将蓝色相机带到森林中并录制两天的视频。

    如果他在第N天使用其中一台摄像机开始录制,则该摄像机仅录制一天。

    每个摄像机可以连续观察森林的K个连续的区域。

    作者已经获得了有关每天在每个区域看到多少动物的信息。由于他想观察尽可能多的动物,因此他希望你找到放置两台摄像机N天的最佳方法。请注意,如果两个摄像机在同一天观察同一区域,则在该区域观察到的动物仅被计数一次。

    输出一个整数,可以观察到的最大动物的数量。

    题解:

    开一个二维数组记录每一天每个区域的动物数量。

    开一个二维数组保存每一天每个区域的前缀和,方便统计。

    然后开一个二维dp数组,i表示第i天,j表示从j开始到j+k-1的区域,dp的值表示当前该区域所能拍摄的最大动物数量(前面的日子最大化操作)。

    初始化dp数组,第1天dp值为区域当天的动物总和。

    然后遍历第2天到第N天,每一天开始,先更新所有的dp值,即把dp值直接加上新一天区域内动物总和。

    然后遍历每个区域,把与前一天拍到的重复的区域剪掉,再更新dp的值。

    更新dp值这个过程需要维护一颗线段树,线段树里的mx值表示前一天能拍到动物的最大数量,tag表示子节点要加多少,存在父节点里,等查询到子节点了再更新子节点。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=20014;
    struct node {
        int l;
        int r;
        int mx;
        int tag;
    }segTree[maxn*4];
    int N,M,K;
    int a[60][maxn];
    int sum[60][maxn];
    int dp[60][maxn];
    void build (int i,int l,int r,int x) {
        segTree[i].l=l;
        segTree[i].r=r;
        segTree[i].tag=0;
        if (l==r-1) 
            segTree[i].mx=dp[x-1][l]+sum[x][l+K-1]-sum[x][max(K-1,l-1)];
        else {
            int mid=(l+r)>>1;
            build(i<<1,l,mid,x);
            build(i<<1|1,mid,r,x);
            segTree[i].mx=max(segTree[i<<1].mx,segTree[i<<1|1].mx);
        }
    }
    void pushdown (int i) {
        segTree[i<<1].mx+=segTree[i].tag;
        segTree[i<<1|1].mx+=segTree[i].tag;
        segTree[i<<1].tag+=segTree[i].tag;
        segTree[i<<1|1].tag+=segTree[i].tag;
        segTree[i].tag=0;
    }
    void modify (int i,int l,int r,int del) {
        if (l<=segTree[i].l&&r>=segTree[i].r) {
            segTree[i].mx+=del;
            segTree[i].tag+=del;
            return;
        }
        if (segTree[i].tag) pushdown(i);
        int mid=(segTree[i].l+segTree[i].r)>>1;
        if (l<mid) modify(i<<1,l,r,del);
        if (r>mid) modify(i<<1|1,l,r,del);
        segTree[i].mx=max(segTree[i<<1].mx,segTree[i<<1|1].mx);
    }
    void solve () {
        scanf("%d%d%d",&N,&M,&K);
        for (int i=1;i<=N;i++) {
            sum[i][0]=0;
            for (int j=1;j<=M;j++) {
                scanf("%d",&a[i][j]);
                sum[i][j]=sum[i][j-1]+a[i][j];
            }
        }
        for (int j=1;j<=M-K+1;j++) 
            dp[1][j]=sum[1][j+K-1]-sum[1][j-1];
        for (int i=2;i<=N;i++) {
            build(1,1,M-K+2,i);
            for (int j=1;j<=M-K+1;j++) {
                modify(1,j,j+K,-a[i][j+K-1]);
                dp[i][j]=segTree[1].mx+sum[i][j+K-1]-sum[i][j-1];
                modify(1,max(j-K+1,1),j+1,a[i][j]);
            }
        }
        int ans=dp[N][1];
        for (int j=2;j<=M;j++)
            ans=max(ans,dp[N][j]);
        printf ("%d\n",ans);
    }
    int main () {
        solve();
        return 0;
    }
  • 相关阅读:
    洛谷 P1823 音乐会的等待
    [The Diary] 10.30 Monday
    洛谷 P1094 纪念品分组
    codevs 1258 关路灯
    NOIP 2012 国王游戏(60分)
    bzoj3745 [COCI2015]Norma
    CF1110E Magic Stones
    bzoj4237 稻草人
    bzoj2653 middle
    单调队列与斜率优化杂题
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12426231.html
Copyright © 2011-2022 走看看