luoguP2184 贪婪大陆 题解(树状数组)

P2184 贪婪大陆  题目

其实很容易理解就是询问一段区间内有多少段不同的区间

然后再仔细思索一下会发现:

1.只要一个区间的开头在一个节点i的左边,那么这个区间包含在区间1~i中。

2.只要一个区间的尾部在一个节点j的左边,那么这个区间肯定不属于j之后的所有区间

这时候就不难想到用两个树状数组维护:

第一个:维护节点i之前有多少个区间的开头

第二个:维护节点j之前有多少个区间的结尾

不难证明拿sum[i]-sum[j]得到的就是i~j中间地雷的个数(手动模拟一波就一清二楚了)

 #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iomanip>
    #include<algorithm>
    #include<stack>
    #include<queue>
    #define lst long long
    #define rg register
    #define N 100050
    using namespace std;
    int n,m;
    lst ans;
    int tou[N],wei[N];//tou存前面有多少个区间的开始,以下简称头部树状数组
                      //wei存前面有多少个区间的尾部,以下简称尾部树状数组
                      //类似于前缀和
    inline int read()//读入优化
    {
        rg int s=0,m=1;rg char ch=getchar();
        while(ch!=‘-‘&&(ch<‘0‘||ch>‘9‘))ch=getchar();
        if(ch==‘-‘)m=-1,ch=getchar();
        while(ch>=‘0‘&&ch<=‘9‘)s=(s<<3)+(s<<1)+ch-‘0‘,ch=getchar();
        return s*m;
    }
    //以下是树状数组的板子
    inline int lowbit(rg int kk)//lowbit
    {
        return kk&(-kk);
    }
    inline void add_tou(rg int kk)//加入树状数组的头部数组
    {
        while(kk<=n)
        {
            ++tou[kk];
            kk+=lowbit(kk);
        }
    }
    inline void add_wei(rg int kk)//加入树状数组的尾部数组
    {
        while(kk<=n)
        {
            ++wei[kk];
            kk+=lowbit(kk);
        }
    }
    inline int sum_tou(rg int kk)//计算节点前有多少个区间的开始
    {
        rg int s=0;
        while(kk>0)
        {
            s+=tou[kk];
            kk-=lowbit(kk);
        }
        return s;
    }
    inline int sum_wei(rg int kk)//计算节点前有多少个区间的结束
    {
        rg int s=0;
        while(kk>0)
        {
            s+=wei[kk];
            kk-=lowbit(kk);
        }
        return s;
    }
    int main()
    {
        n=read(),m=read();//读入
        for(rg int i=1;i<=m;++i)
        {
            rg int sign=read();
            rg int x=read(),y=read();//读入
            if(sign==1)
            {
                add_tou(x);//加入头部树状数组
                add_wei(y);//加入尾部树状数组
            }
            else
            {
                ans=sum_tou(y)-sum_wei(x-1);//运用已经证明的规律结题
                printf("%d\n",ans);
            }
        }
        return 0;
    }

通过这道题,我们可以发现大部分的树状数组题目可以用线段树做,但也有线段树不好维护的题目,这就需要灵活的利用树状数组的技巧(虽然题解里也有线段树比较好理解的) 我自认为我的代码还是蛮好看的,只是变量有点丑,但好理解

原文地址:https://www.cnblogs.com/cjoierljl/p/8783506.html

时间: 2024-11-08 13:55:59

luoguP2184 贪婪大陆 题解(树状数组)的相关文章

[luoguP2184] 贪婪大陆(树状数组)

传送门 用两个树状数组,cr 维护 1....x 中 r 的数量 cl 维护 1....x 中 l 的数量 求答案的时候只需要求 y 前面 被作为左端点 的个数 - x 前面 被作为右端点的个数 ——代码 1 #include <cstdio> 2 3 using namespace std; 4 5 const int MAXN = 1000001; 6 int n, m; 7 int cl[MAXN], cr[MAXN]; 8 9 inline void add1(int x) { for

[CTSC2017]最长上升自序列(伪题解)(树状数组+DP套DP+最小费用最大流+Johnson最短路+Yang_Tableau)

部分分做法很多,但每想出来一个也就多5-10分.正解还不会,下面是各种部分分做法: Subtask 1:k=1 LCS长度最长为1,也就是说不存在j>i和a[j]>a[i]同时成立.显然就是一个LDS,树状数组直接求即可. Subtask 2:k=2 最多两个,也就是可以由两个LCS拼起来,f[i][j]表示第一个LCS以i结尾,第二个以j结尾的方案数,转移显然. Subtask 3:k=2 树状数组优化DP,复杂度由$O(n^3)$降为$O(n^2 \log n)$ Subtask 4,5:

【bzoj2789】[Poi2012]Letters 树状数组求逆序对

题目描述 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. 输入 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度. 第二行和第三行各一个长度为n的字符串,并且只包含大写英文字母. 输出 一个非负整数,表示最少的交换次数. 样例输入 3 ABC BCA 样例输出 2 题解 树状数组求逆序对 一个结论:将序列A通过交换相邻元素变换为序列B,需要的最小次数为A中

【树状数组】Bzoj1878[SDOI2009] HH的项链

Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答...因为项链实在是太长了.于是,他只好求助睿智的你,来解 决这个问题. Input 第一行:一个整数N,表示项链的长度. 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的

【bzoj4994】[Usaco2017 Feb]Why Did the Cow Cross the Road III 树状数组

题目描述 给定长度为2N的序列,1~N各处现过2次,i第一次出现位置记为ai,第二次记为bi,求满足ai<aj<bi<bj的对数 样例输入 4 3 2 4 4 1 3 2 1 样例输出 3 题解 树状数组 WH说是CDQ分治直接把我整蒙了... 把所有数按照第一次出现位置从小到大排序,然后扫一遍.此时一定是满足$a_j>a_i$的. 那么只需要求出$(a_j,b_j)$中以前出现过的$b_i$的数目.使用树状数组维护即可. 时间复杂度$O(n\log n)$ #include &l

贪婪大陆 树状数组

题目背景 面对蚂蚁们的疯狂进攻,小FF的Tower defence宣告失败--人类被蚂蚁们逼到了Greed Island上的一个海湾.现在,小FF的后方是一望无际的大海, 前方是变异了的超级蚂蚁. 小FF还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造SCV布置地雷以阻挡蚂蚁们的进攻. 题目描述 小FF最后一道防线是一条长度为N的战壕, 小FF拥有无数多种地雷,而SCV每次可以在[ L , R ]区间埋放同一种不同于之前已经埋放的地雷. 由于情况已经十万火急,小FF在某些时候可能会询

洛谷 P3374 【模板】树状数组 1 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=3374 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操

【题解】Leyni,罗莉和队列(树状数组)

[题解]Leyni,罗莉和队列(树状数组) HRBUST - 1356 将整个序列reverse一下,现在就变成了从高到低的排队.题目就变成了,定位一个妹子,问这个妹子前面的比这个妹子小的妹子中,下标最小的数是哪个. 所以以年龄为下标,以(原数组)下标为值建立一颗值域线段树,由于我们只要找到在原数组下标最小的哪一个,所以相当于动态维护前缀\(\min\) ,由于我们只要查询比当前定位妹子小的一段前缀,所以拿树状数组代替就是了. 由于这群妹子是神仙(年龄可达1e9),所以要离散化一下. 复杂度\(

【题解】[CJOI2019] 树上查询(树状数组)

[题解][CJOI2019] 树上查询(树状数组) 题目描述 班?小 A 需要管理信息组的日常纪律.所有人都在树形机房学习,树形机房的根节点为 1 .信息组的同学很多,但树 形机房的每个节点上有且仅有一个同学.小 A 的位置在树形机房的某个节点上,他想要管理在他所站节点子树中的同学(不算自己).每个位置都有一个管理容易值\(w_i\) ,他能管理到某个位置 ,当且仅当他们的距离不超过\(w_i\). 定位一个根\(x\),现在就是求\(u\in S\),\(S\)是\(x\)的所有子树所有节点集