zoukankan      html  css  js  c++  java
  • 【*篇】luogu2184贪婪大陆

    题目在这里哦, 戳一下就可以了~

    题目大意:
    支持两种操作,区间添加一种新元素,查询区间颜色种数..

    题目标签是线段树啊,我也本来想写一个线段树,后来写不出来……(我太弱了orz)
    然后就草率地看了看题解里面的思路咯,感觉思路非常的不错,于是我就A掉这题之后写了这篇blog…

    图解
    我们通过这幅图可以看到:
    - 我们直接统计区间的覆盖不是很好统计, 考虑前缀
    - 当前我们已经进行了10次覆盖
    - 从[1,R]这个区间中有9个覆盖
    - 但是其中有3个覆盖完全在L的左侧(即右端点在[1,L-1])
    - 所以应该只有6次覆盖在[L,R]范围内
    - ∴ans=6

    我们可以发现,这是一个区间覆盖的问题,询问的答案是[1,r]中的种类数减去[1,l-1] 中的右端点数…
    然后此题就沦为了一道区间和单点修改单点和区间查询的题目…
    我们可以用两个不同的数据结构来分别维护右端点数目和种类数…我们整理了一下发现:
    - 对于右端点,我们修改的时候在右端点单点加,查询的时候区间查询[1,l-1]..
    - 对于种类数,我们修改的时候做区间加,往区间[l,n]加上,查询的时候单点查 r点的值..

    所以,一个单点加区间查,一个区间加单点查,就是这样两个树状数组的基本操作了…
    而区间操作都是含1和n的,所以我们就可以省掉一些步骤..
    最后写出来就是这样:

    #include <cstdio>
    const int N=101010;
    inline int gnum(){
        int a=0;char c=getchar();for(;c<'0'||c>'9';c=getchar());
        for(;c>='0'&&c<='9';c=getchar()) a=(a<<1)+(a<<3)+c-'0'; return a;
    } 
    int t[2][N],n,m;
    void add(int *c,int x){for(;x<=n;x+=x&-x)++c[x];}
    int query(int *c,int x){int s=0;for(;x;x-=x&-x)s+=c[x];return s;}
    int main(){
        n=gnum(),m=gnum();
        for(int i=1;i<=m;++i){
            int o=gnum(),l=gnum(),r=gnum();
            //端点:单点r加1 区间1..l-1查
            //种类:区间l..n加1 单点r查
            if(o-2) add(t[0],l),add(t[1],r);
            else printf("%d
    ",query(t[0],r)-query(t[1],l-1));
        }
    }

    这样就可以咯~

  • 相关阅读:
    关于spring中Assert的应用(方法入参检测工具类)
    索引与排序,重复索引与冗余索引,索引碎片与维护
    大数据量分页优化
    理想的索引
    索引覆盖
    聚簇索引
    mysql 索引
    表的优化与列类型选择
    mysql show profiles 使用分析sql 性能
    show processlist,sysbench压力测试工具
  • 原文地址:https://www.cnblogs.com/enzymii/p/8412135.html
Copyright © 2011-2022 走看看