2018牛客多校第二场

J.farm(二维树状数组)

题意:给一个n*m的矩阵,每个格子里面都有一种植物(类型可能不同),进行q次操作,每次往给出的区域里面浇灌一种类型农药,如果农药和植物的类型不一样这个植物就会死掉,问进行了所有的操作以后死掉的植物的种类。

题解:本来以为用二维树状数组或者线段树都会T所以比赛时候就没有做,但赛后发现都是可行的。每次喷农药的时候将这个区间内的植物的贡献都加一。 然后对于[1,n*m]的所有植物, 先删除同种植物的同种农药对区间的影响, 然后查询该种植物的是否被标记过了 即 该位置的值 > 1, 最后处理完这种植物再把这种植物的农药再加回去。

附上代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod=1000000007;
const int maxn = 1e6 + 100;
vector<int> s[maxn];
vector<pll> q[maxn];
int n, m;
struct node
{
        int x1, y1, x2, y2, k;
    bool operator<(const node&aa)const
    {
        return aa.k>k;
    }
}a[maxn];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x, int y, int c)
{
        for(int i = x; i <= n; i+=lowbit(i))
                for(int j = y; j <= m; j += lowbit(j))
                        s[i][j] += c;
}
int query(int x, int y)
{
        int cnt = 0;
        for(int i = x; i > 0; i -= lowbit(i))
                for(int j = y; j > 0; j -= lowbit(j))
                       cnt += s[i][j];
        return cnt;
}
int main()
{
        int  t, v;
        int ans = 0;
        scanf("%d%d%d", &n, &m, &t);
        for(int i = 1; i <= n; i++)
                s[i].resize(m+10);
        for(int i = 1; i <= n; i++)
    {
                for(int j = 1; j <= m; j++)
        {
                        scanf("%d", &v);
                        q[v].push_back(pll(i,j));
                   
        }
           
    }
        for(int i = 1; i <= t; i++)
    {
                scanf("%d%d%d%d%d", &a[i].x1, &a[i].y1, &a[i].x2, &a[i].y2, &a[i].k);
                add(a[i].x1, a[i].y1, 1);
                add(a[i].x2+1,a[i].y2+1,1);
                add(a[i].x1,a[i].y2+1,-1);
                add(a[i].x2+1,a[i].y1,-1);
           
    }
        sort(a+1,a+1+t);
        for(int i = 1, j = 1, zz; i <= n * m; i++)
    {
          
                while(a[j].k < i && j <= t)   j++;
                if(q[i].size() == 0) continue;
                zz = j;
                while(a[zz].k == i && zz <=t) zz++;
                for(int z = j; z < zz; ++z)
        {
                        add(a[z].x2+1,a[z].y2+1,-1);
                        add(a[z].x1,a[z].y1,-1);
                        add(a[z].x1,a[z].y2+1,1);
                        add(a[z].x2+1,a[z].y1,1);
                   
        }
                for(auto it : q[i])
        {
                        if(query(it.first, it.second))
            {
                                ans++;
                           
            }
                   
        }
                for(int z = j; z < zz; ++z)
        {
                        add(a[z].x2+1,a[z].y2+1,1);
                        add(a[z].x1,a[z].y1,1);
                        add(a[z].x1,a[z].y2+1,-1);
                        add(a[z].x2+1,a[z].y1,-1);
                   
        }
                j = zz;
           
    }
        printf("%d\n",ans);
        return 0;
}

猜你喜欢

转载自blog.csdn.net/wookaikaiko/article/details/81152446