题目链接

分析 :

最简单的想法当然就是去模拟

直接对每个施肥料的操作进行模拟、然后计算贡献

但是这显然会超时、这题需要换一个思维

对于一个土地(也就是二维平面上的一个点)的种类是 T'

如果它被操作了 K1 次、那么如果我能知道所有用 T' 施肥的操作

对这块土地施肥的次数 K2、那么当 K1 == K2 的时候、这片土地就不会 Die

而当 K1 != K2 的时候、则这块土地就会 Die 、换句话说就是答案要加一

计算每个土地被操作的总次数

要知道每个土地被操作了多少次、可以利用二维前缀和的方式来计算贡献

假设操作矩形的左上角和右下角分别为 (x1, y1) 、(x2, y2)

那么可以用二维数组模拟这个矩形的四个顶点分别做加减操作

具体的就是 arr[x1][y1]++、arr[x1][y2+1]--、arr[x2+1][y1]--、arr[x2][y2]++

然后 N*M 地去遍历整个土地、利用这条式子 arr[i][j] += arr[i-1][j] + arr[i][j-1] - arr[i-1][j-1]

最后 arr 这个二维数组中所有的数字表示的即为某一块土地被操作的总次数

计算被用于操作的肥料对其施肥的土地操作的总次数

如果仔细思考一下便会发现这个是一个很经典的二维偏序问题

如果你解决过类似 CDQ 分治的题目、那么这个便会很容易理解

对于每个种类的肥料、其可能被用于若干次施肥操作

施肥操作是一个矩形、可以将矩形操作分解成四个点的加减操作

也就是将一个操作变成四个操作、如果你熟悉 CDQ 分治、那么这个会好理解

可以发现对于每一个点、在二维平面上只有其左上角的操作点对它有影响

所以每次处理都将所有操作对于 X 轴先进行排序、然后利用树状数组维护 Y 轴

还有一开始的原矩形元素也应该被视作操作、保存到分治数组里面去、用于问询

可能很乱,看代码就清楚了

(最好是你先去熟悉偏序问题和CDQ分治、因为代码的很多细节都是套路操作、不赘述了)

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;
;

struct ARR{
    int r, c, op;
    ARR(){};
    ARR(int _r, int _c, int _o):r(_r), c(_c), op(_o){};
    bool operator < (const ARR & rhs) const{
        if(r == rhs.r && c == rhs.c) return abs(op) > abs(rhs.op);
        if(r == rhs.r) return c < rhs.c;
        return r < rhs.r;
    }
}; vector<ARR> arr[maxn];

int n, m, T;
];
int Bit[maxn];

inline void BitAdd(int i, int val)
{
    while(i <= m){
        Bit[i] += val;
        i += (i & (-i));
    }
}

int BitSum(int i)
{
    ) ;
    ;
    ){
        ret += Bit[i];
        i -= (i & (-i));
    }return ret;
}

void BitClean(int i)
{
    while(i <= m){
        Bit[i] = ;
        i += (i & (-i));
    }
}

int idx(int r, int c)
{ return r * m + c; }

int main(void){__stTIME();__IOPUT();

    sciii(n, m, T);

    ; i<=n; i++)
        ; j<=m; j++){
            int tmp; sci(tmp);
            arr[tmp].pb(ARR(i, j, ));
        }

    ; i<T; i++){
        int x1, y1, x2, y2, k;
        sciiii(x1, y1, x2, y2); sci(k);
        arr[k].pb(ARR(x1, y1, ));
        arr[k].pb(ARR(x1, y2+, -));
        arr[k].pb(ARR(x2+, y1, -));
        arr[k].pb(ARR(x2+, y2+, ));
        Cnt[idx(x1, y1)]++;
        Cnt[idx(x1, y2+)]--;
        Cnt[idx(x2+, y1)]--;
        Cnt[idx(x2+, y2+)]++;
    }

    ; i<=n; i++)
        ; j<=m; j++)
            Cnt[idx(i, j)] += Cnt[idx(i-, j)] +
                              Cnt[idx(i, j-)] -
                              Cnt[idx(i-, j-)];

//    for(int i=1; i<=n; i++,puts(""))
//        for(int j=1; j<=m; j++)
//            printf("%d ", Cnt[idx(i, j)]);

    ;
    ; i<=n*m; i++){
        sort(all(arr[i]));
        //printf("----- %d ------\n", i);
        ; j<(int)arr[i].size(); j++){
            //printf("$$=> %d %d %d\n", arr[i][j].r, arr[i][j].c, arr[i][j].op);
            ){
                if(Cnt[idx(arr[i][j].r, arr[i][j].c)] != BitSum(arr[i][j].c))
                    ans++;
            }else BitAdd(arr[i][j].c, arr[i][j].op);
        }
        ; j<(int)arr[i].size(); j++){
            )
                BitClean(arr[i][j].c);
        }
    }

    printf("%d\n", ans);

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

Nowcoder farm ( 树状数组、二维前缀和、二维偏序 )的更多相关文章

  1. HDU 5465——Clarke and puzzle——————【树状数组BIT维护前缀和+Nim博弈】

    Clarke and puzzle Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  2. [POI2005]AUT-The Bus 树状数组维护最大前缀和

    #include<cstdio> #include<algorithm> using namespace std; const int N=100000+3; int x[N] ...

  3. [POI2007]MEG-Megalopolis 树状数组 + dfs序前缀和 好题

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const ...

  4. HH的项链 树状数组动态维护前缀

    #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const ...

  5. 牛客网 暑期ACM多校训练营(第二场)J.farm-STL(vector)+二维树状数组区间更新、单点查询 or 大暴力?

    开心.jpg J.farm 先解释一下题意,题意就是一个n*m的矩形区域,每个点代表一个植物,然后不同的植物对应不同的适合的肥料k,如果植物被撒上不适合的肥料就会死掉.然后题目将每个点适合的肥料种类( ...

  6. 【二维树状数组】【CF10D】 LCIS

    传送门 Description 给你两个串,求他们的最长公共上升子序列 Input 第一行是第一个串的长度\(n\) 第二行\(n\)个数代表第一个串 第三行是第二个串的长度\(m\) 第四行\(m\ ...

  7. 二维树状数组总结&&【洛谷P4514】 上帝造题的七分钟

    P4514 上帝造题的七分钟 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了00的n×mn×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b)(a,b),右下 ...

  8. POJ_2155 Matrix 【二维树状数组】

    一.题面 POJ2155 二.分析 楼教主出的题,是二维树状数组非常好的题,还结合了开关问题(开关变化的次数如果为偶数,状态不变,奇数状态相反). 题意就是给了一个二维的坐标平面,每个点初始值都是0, ...

  9. 1042.D Petya and Array 前缀 + 树状数组

    11.19.2018 1042.D Petya and ArrayNew Point: 前缀 + 树状数组 :树状数组逐个维护前缀个数 Describe: 给你一个数组,一个标记数,问你有多少区间[l ...

随机推荐

  1. sql实现同时向主表和子表插入数据方法

    使用sql语句实现同时向主表和子表插入数据方法: Oracle: -- oracle创建sequence create sequence SEQ_test minvalue 1 maxvalue 99 ...

  2. C++11智能指针原理和实现

    一.智能指针起因 在C++中,动态内存的管理是由程序员自己申请和释放的,用一对运算符完成:new和delete. new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针: delete:指向 ...

  3. Luogu P2617 Dynamic Rankings(整体二分)

    题目 动态区间第K小模板题. 一个非常可行的办法是BIT套动态开点权值SegTree,但是它跑的实在太慢了. 然后由于这题并没有强制在线,所以我们可以使用整体二分来吊打树套树. 当然如果强制在线的话就 ...

  4. python-day9(正式学习)

    目录 深浅拷贝 拷贝 浅拷贝 深拷贝 异常处理 什么是异常 语法错误 逻辑错误 异常的种类 常用的异常 其他异常 异常处理 提前预防 事后预防 抛出异常(基本没用) 断言(调试用,现在基本上没用) 文 ...

  5. Django创建数据库常用字段及参数

    Django创建数据库常用字段及参数 常用字段 1.models.AutoField 自增列= int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列 ...

  6. C++ 多态、虚函数(virtual 关键字)、静态联编、动态联编

    函数重写:(在子类中重写父类中的函数) 父类中被重写的函数  依然会继承  给子类. 子类中重写的函数将覆盖父类中的函数. 通过作用域分辨符  ::  可以访问到父类中的函数. 例如: #includ ...

  7. WPF:元素绑定

    到目前为止都在讨论如何链接两个元素的绑定.但在数据驱动的应用程序中,更常见的情况是创建从不可见的对象中提取数据绑定表达式.唯一的要求是希望显示的信息必须存储在公有的属性中.WPF数据绑定基础结构不能获 ...

  8. python 写入JSON中文乱码解决方法

    在将一个字典添加入json中时多加入一个参数就可以了 json.dumps(dict(item), ensure_ascii=False) 例子 with open('zh-cn.json','w', ...

  9. lwip 内存配置和使用,以及 如何 计算 lwip 使用了多少内存?

    /** * 内存配置 * suozhang 2019年9月6日20:25:48 参考 <<LwIP 应用开发实战指南>> 野火 第5章 LwIP 的内存管理 * * 动态内存池 ...

  10. Python数据驱动DDT的应用

    在开始之前,我们先来明确一下什么是数据驱动,在百度百科中数据驱动的解释是:数据驱动测试,即黑盒测试(Black-box Testing),又称为功能测试,是把测试对象看作一个黑盒子.利用黑盒测试法进行 ...