zoukankan      html  css  js  c++  java
  • 2018牛客暑假多校二 J(二维树状数组)

    题目意思:

        有一个n*m的矩形,每个位置有一个数。有T次操作,每次往一个子矩形的每个格子中放入一个数。 求有多少个格子中被放入了至少一个与对应位置不相同的数。 n*m<=1e6,T<=1e6。

    题目分析:

        对于这个题,因为我们需要处理的是一个矩形区域的问题,因为我们不难想到可以用二维线段树/二维树状数组去做。(但是鉴于线段树常数过大,而这个题还是挺卡时间的,因此最好采用二维树状数组进行解决)。

        我们可以考虑这样的一个做法:我们用一个vector存储某一种药可以作用在哪一些点上;再用一个vector存储T种方案中,每一个种类的药所涉及的范围。假设某一点没有被药所覆盖,该点为0,否则该点大于0。则我们在每一种方案浇花的时,我们用二位树状数组在[x1,y1],[x2,y2]这样的二维空间加1,代表被一种药浇到了。

        最后就是整个做法的精髓:我们遍历所有的药的种类,先判断是否这种药是否可以作用在某一点上,如果可行,就遍历所有的有该药的花的区间,消除它的影响。然后再遍历所有的以这种药为生的花,判断是否会死(此时如果遍历的结果发现该花所在的区间不为0,即有其他的药作用在这个花的区间了,则代表花必死)。

        这样不断的遍历即可获得答案。

        具体细节在代码中有所标记。

    代码:

    #include <bits/stdc++.h>
    #define maxn 1000005
    using namespace std;
    typedef long long ll;
    typedef pair<int,int>PLL;
    vector<int>bit[maxn];//vector bit是二维树状数组
    vector<PLL>a[maxn];//vector a存储的是第i种药所对应的坐标
    struct node{
        int a,b,c,d;
        node(int _a,int _b,int _c,int _d){
            a=_a,b=_b,c=_c,d=_d;
        }
    };
    vector<node>q[maxn];//vector q存储的是第i种药品所撒的区间
    int n,m,t;
    int lowbit(int x){
        return x&-x;
    }
    void add(int x,int y,int z){
        for(int i=x;i<=n;i+=lowbit(i)){
            for(int j=y;j<=m;j+=lowbit(j))
                bit[i][j]+=z;
        }
    }
    void update(int x1,int y1,int x2,int y2,int z){
        add(x1,y1,z);
        add(x2+1,y2+1,z);
        add(x1,y2+1,-z);
        add(x2+1,y1,-z);
    }
    int query(int x,int y){
        int res=0;
        for(int i=x;i;i-=lowbit(i)){
            for(int j=y;j;j-=lowbit(j)){
                res+=bit[i][j];
            }
        }
        return res;
    }
    unsigned int read()//读入挂
    {
        unsigned int ret=0;
        char ch=getchar();
        while(ch>'9'||ch<'0')ch=getchar();
        while(ch>='0'&&ch<='9')
        {
            ret=ret*10+ch-'0';
            ch=getchar();
        }
        return ret;
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&t);
        for(int i=1;i<=n;i++) bit[i].resize(m+1);//预开空间
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                int z;
                z=read();
                //scanf("%d",&z);
                a[z].push_back(make_pair(i,j));
            }
        }
        for(int i=1;i<=t;i++){
            int a,b,c,d,k;
            a=read(),b=read(),c=read(),d=read(),k=read();
            //scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
            update(a,b,c,d,1);//将这一片区间置1
            q[k].push_back(node(a,b,c,d));
        }
        int ans=0;
        for(int i=1;i<=n*m;i++){//枚举每一种药
            if(a[i].size()){//如果有某种花许需要第i种药
                for(auto nw:q[i])//遍历所有的有该药的区间,消除它的影响
                    update(nw.a,nw.b,nw.c,nw.d,-1);
                for(auto nw:a[i]){//遍历所有的以这种药为生的花,判断是否会作用
                    if(query(nw.first,nw.second)) ans++;
                }
                for(auto nw:q[i])//回复这种药的作用。
                    update(nw.a,nw.b,nw.c,nw.d,1);
            }
        }
        cout<<ans<<endl;//输出结果!
        return 0;
    }
    
  • 相关阅读:
    Silverlight实用窍门系列:68.Silverlight的资源字典ResourceDictionary
    在HyperlinkButton的URL地址里附加多个参数(以http get的方式)
    SilverLight CheckBox 控件 DataContext属性与DataContextChanged事件
    关于事件在意料之外触发的问题
    关于Telerik RadGridView 数据列拖动后异常的一种情况
    silverlight使用小计(先做记录后续整理)
    Redis_简介和安装
    Python并行系统工具_multiprocessing模块
    Python并行系统工具_程序退出和进程间通信
    Python并行系统工具_进程分支
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007264.html
Copyright © 2011-2022 走看看