zoukankan      html  css  js  c++  java
  • p1247

    看到n,m<=100000可以想到这是一个考高级数据结构的题,这个区间修改区间查询让我想到了线段树和树状数组。

    然而看了一遍题后眉头一皱,发现并不简单。

    它要求输出区间上炸弹种类数,那么维护区间和也不对,维护区间最大值也不对,看来不能直接套模板了。

    这个时候需要重新综合考虑修改和查询的内容了。经过思考可以想到离散化的方法,把区间修改改成单点修改,区间查询即为求区间∑。

    那么就可以写一个树状数组了, 毕竟代码好写很多很多很多。

    对于每个修改把原数组左右端点所在位置++(注意开两个数组)。

    对于每次询问嘛……

    我们把1-n分为三部分:tl左,tl右tr左和tr右,记为123.那么所有炸弹有左1右1,左1右2,左1右3,左2右2,左2右3,左3右3.

    我们查询的答案为左1右2+左1右3+左2右2+左2右3=sum-左1右1-左3右3.这也体现了数学里的正难则反的原则。

    求法上还可以进一步优化:原式=sum-askyou(l-1)-(sum-sumzuo[r])=sum-zuo[r]-you[r-1];(直接给出这个式子你们应该也能理解)

    本题可A。

    int i,t,tl,tr;
    int m,n;
    int zuo[1000010],you[1000010];
    int lowbit(int x)
    {
        return x&(-x);
    }
    void addzuo(int p,int k)
    {
        while(p<=n)
        {
            zuo[p]+=k;
            p+=lowbit(p);
        }
    }
    void addyou(int p,int k)
    {
        while(p<=n)
        {
            you[p]+=k;
            p+=lowbit(p);
        }
    }
    int sumzuo(int x)
    {
        int ans=0;
        while(x)
        {
            ans+=zuo[x];
            x-=lowbit(x);
        }
        return ans;
    }
    int sumyou(int x)
    {
        int ans=0;
        while(x)
        {
            ans+=you[x];
            x-=lowbit(x);
        }
        return ans;
    }
    int main()
    {
    
        cin>>n>>m;
        
        for(i=1;i<=m;i++)
        {
            cin>>t>>tl>>tr;
            if(t==1)
            {
                addzuo(tl,1);
                addyou(tr,1);
            }
            else
                
                cout<<sumzuo(tr)-sumyou(tl-1)<<endl;
        }
    }

    还好没有卡tl=1或等0的数据,不然就死循环…………

  • 相关阅读:
    人人网笔试题
    创新工厂笔试题
    奇异广告面试
    微策略笔试题
    多玩笔试题
    有道笔试+面试
    巨人网络开发工程师试题
    Hulu笔试题
    百度笔试题
    兰亭集势笔试题
  • 原文地址:https://www.cnblogs.com/qywyt/p/9623261.html
Copyright © 2011-2022 走看看