题意

n*m的农场有若干种不同种类作物,如果作物接受了不同种类的肥料就会枯萎。现在进行t次施肥,每次对一个矩形区域施某种类的肥料。问最后枯萎的作物是多少。

分析

作者:xseventh
链接:https://www.nowcoder.com/discuss/87630?type=101
来源:牛客网

我们通过差分(其实就是二维前缀和)可以在O(nm)的时间求出每个点被撒了几次肥料
然后我们可以对每种植物分开求被撒了几次相同种类的肥料,然后判断被撒肥料的次数是否等于被撒的相同种类肥料的次数来确定这个植物的死活
首先  我们需要学会二维差分,这个怎么做呢?我们发现如果我们想对(x1,y1) (x2,y2)这个矩形内所有元素+1
我们可以通过a[x1][y1]++,a[x1][y2+1]--,a[x2+1][y1]--,a[x2+1][y2+1]++这四个操作来实现
我们对这四个点进行加减后,再对矩阵求一次二维前缀和,这时候的效果就是整个矩形+1了

然后我们开始考虑如何求每种的植物被撒了几次肥料。
我们要分别求n*m种植物被撒了几次肥料,所以我们肯定不能每一次都通过二维前缀和来维护被撒了几次肥料。
这时候我们发现这其实是个二维偏序的问题,我们对每种植物的贡献排序,然后用树状数组维护一下就好了。众所周知 二维偏序的做法复杂度是一个log的,我们一共有n*m次操作,所以总复杂度为O(n*m*log(n*m))
具体怎么维护呢,我们通过对x和y坐标排序,按照顺序把贡献加到树状数组里,树状数组里前面的元素的x坐标一定是小于等于当前元素的,我们只需要求树状数组内<=y的和就能统计出x,y都<=y的元素和
注意一点,当x和y相等的时候,询问一定要在修改后面,排序时候判断一下就行了。
注意 清空树状数组的时候为了保证复杂度,我们只能重新做一次之前的修改,把负的权值加上去。
具体代码如下
#include <bits/stdc++.h>

using namespace std;
int c[];
int n,m;
int id(int i,int j){
return i*(m+)+j;
} struct nod{
int x,y,val;
    bool operator < (const nod &b)const{
        if(x==b.x&&y==b.y){
            return abs(val)>abs(b.val);
        }
        if(x==b.x)
            return y<b.y;
        return x<b.x;
    }
};
vector<nod>vd[];
int bit[];
void add(int pos,int x){
    while(pos<=m+){
        bit[pos]+=x;
        pos+=pos&-pos;
    }
}
int sum(int pos){
    int Sum=;
    while(pos){
        Sum+=bit[pos];
        pos-=pos&-pos;
    }
    return Sum;
}
int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
    int t,x;
    scanf("%d%d%d",&n,&m,&t);
    for(int i=;i<=n;i++)
        for(int j=;j<=m;j++){
            scanf("%d",&x);
            vd[x].push_back(nod{i,j,});
        }
    int x1,x2,y1,y2;
    while(t--){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        int k;
        scanf("%d",&k);
        vd[k].push_back(nod{x1,y1,});
        vd[k].push_back(nod{x2+,y2+,});
        vd[k].push_back(nod{x1,y2+,-});
        vd[k].push_back(nod{x2+,y1,-});
        c[id(x1,y1)]++;
        c[id(x2+,y2+)]++;
        c[id(x1,y2+)]--;
        c[id(x2+,y1)]--;
    }
    for(int i=;i<=n;i++){
        for(int j=;j<=m;j++){
            c[id(i,j)]+=c[id(i-,j)]+c[id(i,j-)]-c[id(i-,j-)];//被撒肥料总次数
        }
    }
    int ans=;
    for(int i=;i<=n*m;i++){
        sort(vd[i].begin(),vd[i].end());
        for(int j=;j<vd[i].size();j++){
            if(vd[i][j].val==){
                if(c[id(vd[i][j].x,vd[i][j].y)]==sum(vd[i][j].y))
                    ans++;
            }
            else {
                add(vd[i][j].y,vd[i][j].val);
            }
        }
        for(int j=;j<vd[i].size();j++)
            if(vd[i][j].val)
            add(vd[i][j].y,-vd[i][j].val);
    }
    printf("%d\n",n*m-ans);
    return ;
}

2018牛客网暑期ACM多校训练营(第二场)J Farm(树状数组)的更多相关文章

  1. 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)

    2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...

  2. 2018牛客网暑期ACM多校训练营(第一场)D图同构,J

    链接:https://www.nowcoder.com/acm/contest/139/D来源:牛客网 同构图:假设G=(V,E)和G1=(V1,E1)是两个图,如果存在一个双射m:V→V1,使得对所 ...

  3. 2018 牛客网暑期ACM多校训练营(第一场) E Removal (DP)

    Removal 链接:https://ac.nowcoder.com/acm/contest/139/E来源:牛客网 题目描述 Bobo has a sequence of integers s1, ...

  4. 2018牛客网暑期ACM多校训练营(第十场)A Rikka with Lowbit (树状数组)

    链接:https://ac.nowcoder.com/acm/contest/148/A 来源:牛客网 Rikka with Lowbit 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C ...

  5. 2018牛客网暑期ACM多校训练营(第十场)J Rikka with Nickname(二分,字符串)

    链接:https://ac.nowcoder.com/acm/contest/148/J?&headNav=acm 来源:牛客网 Rikka with Nickname 时间限制:C/C++ ...

  6. 2018牛客网暑期ACM多校训练营(第一场)B Symmetric Matrix(思维+数列递推)

    题意 给出一个矩阵,矩阵每行的和必须为2,且是一个主对称矩阵.问你大小为n的这样的合法矩阵有多少个. 分析 作者:美食不可负064链接:https://www.nowcoder.com/discuss ...

  7. 2018牛客网暑期ACM多校训练营(第五场) F - take - [数学期望][树状数组]

    题目链接:https://www.nowcoder.com/acm/contest/143/F 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...

  8. 2018牛客网暑期ACM多校训练营(第二场) J - farm - [随机数哈希+二维树状数组]

    题目链接:https://www.nowcoder.com/acm/contest/140/J 时间限制:C/C++ 4秒,其他语言8秒 空间限制:C/C++ 262144K,其他语言524288K ...

  9. 2018牛客网暑期ACM多校训练营(第三场) A - PACM Team - [四维01背包][四约束01背包]

    题目链接:https://www.nowcoder.com/acm/contest/141/A 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ...

随机推荐

  1. centos6.8下普通用户下quartus编程识别不到用户开发板

    前言 centos6.8下su用户下可以识别到用户的板子,能正常下板,而普通用户下无法探测到用户板子. 需要配置一下usb-blaster,不然的话,虽然quartus软件能识别,但是无法探测到FPG ...

  2. IDEA 不识别的MAVEN 项目应如何处理

    有些人啊,上传到git的项目,根本不是项目而是一个文件夹,文件夹里边还有个文件夹那才是项目,IDEA 不会识别出它是项目来 这个时候,需要选择这个文件夹下的pom.xml 文件 右键 pom.xml然 ...

  3. python3 fileinput模块

    模块fileinput可以对一个或多个文件的内容所有行进行迭代.遍历等操作: 常用方法: fileinput.input(files=None, inplace=False, backup='', b ...

  4. 【BZOJ1022】小约翰的游戏(博弈论)

    [BZOJ1022]小约翰的游戏(博弈论) 题面 BZOJ 题解 \(Anti-SG\)游戏的模板题目. #include<iostream> #include<cstdio> ...

  5. 「SCOI2015」国旗计划 解题报告

    「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...

  6. 配置日志中显示IP

    package com.demo.conf; import ch.qos.logback.classic.pattern.ClassicConverter; import ch.qos.logback ...

  7. bzoj1047/luogu2216 理想的正方形 (单调队列)

    开b组单调队列,分别维护此时某一列中的最大/最小值 然后我每次把它们的头取出来,塞到维护行的单调队列里,就是n*n的最大/最小值 #include<bits/stdc++.h> #defi ...

  8. 解决Oracle死锁问题步骤

    出现问题: 使用jdbc进行批量插入,一直卡在执行界面上,不走代码,预估应该是产生了死锁 1. 使用如下语句查询oracle数据库中的死锁的表和死锁类型 select b.owner,b.object ...

  9. Linux包系列的知识(附:Ubuntu16.04升级到18.04的案例)

    Linux基础:https://www.cnblogs.com/dunitian/p/4822808.html#linux 之前看到朋友还动不动 apt-get update upgrade,就很纳闷 ...

  10. 牛客练习赛31 D神器大师泰兹瑞与威穆

    双链表搞完了 #include<bits/stdc++.h> using namespace std; #define maxn 1000005 int tot,bac[maxn],fa[ ...