冷静 清醒 直视|

艾特玖

园龄:3年11个月粉丝:12关注:7

P2184 贪婪大陆

P2184 贪婪大陆

分析

有点意思的题目的,我们用两种方法来解决。

我们要求的东西就是,在区间[l,r]中,包含的不同的区间个数

更进一步,求得是之前的区间中与区间[l,r]相交的不同区间个数

那问题就变成了,如何判断是否与区间[l,r]相交呢?

这就好说了,区间[l',r']只要满足,l'<=r且l<=r'即可

树状数组

这就很自然想到树状数组了,树状数组的一大经典利用,我们需要知道关于坐标的区间问题,则按照值插入,这样根据对值的限定,就知道坐标的数量了

不难想到,我们这里需要维护两个树状数组,一个是关于区间的左端点的,一个是关于区间的右端点的。

这样,我们想知道区间[l',r']是否满足l'<=r且l<=r'

直接用树状数组判断即可。

直接看代码吧!!

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int tr1[N],tr2[N];
int n,m;

int lowbit(int x)
{
    return x & -x;
}

void add(int tr[],int x)
{
    while(x<=n)
    {
        tr[x] ++;
        x += lowbit(x);
    }
}

int sum(int tr[],int x)
{
    int res = 0;
    while(x)
    {
        res += tr[x];
        x -= lowbit(x);
    }
    return res;
}

int main()
{
    scanf("%d%d",&n,&m);
    while(m--)
    {
        int op,l,r;scanf("%d%d%d",&op,&l,&r);
        if(op==1) add(tr1,l),add(tr2,r);
        else printf("%d\n",sum(tr2,n) - sum(tr2,l-1) - (sum(tr1,n) - sum(tr1,r)));
    }
    return 0;
}

线段树

我们也可以用线段树来完成这个操作。利用的是差分的思想

对于区间[l,r]而言,我们想知道的就是,对于从[1,r]内的左端点,有多少是已经在[1,l-1]中就已经有匹配的右端点了,减去他们就是解了

直接看看代码。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct Node
{
    int l,r,sum[2];
}tr[N<<2];
int n,m;

void pushup(int u)
{
    tr[u].sum[0] = tr[u<<1].sum[0] + tr[u<<1|1].sum[0];
    tr[u].sum[1] = tr[u<<1].sum[1] + tr[u<<1|1].sum[1];
}

void build(int u,int l,int r)
{
    tr[u] = {l,r};
    if(l==r) return ;
    int mid = l + r >> 1;
    build(u<<1,l,mid),build(u<<1|1,mid+1,r);
    pushup(u);
}

void modify(int u,int x,int f)
{
    if(tr[u].l==tr[u].r) 
    {
        tr[u].sum[f] ++;
        return ;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if(x<=mid) modify(u<<1,x,f);
    else modify(u<<1|1,x,f);
    pushup(u);
}

int query(int u,int l,int r,int f)
{
    if(l>r) return 0;
    if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum[f];
    int mid = tr[u].l + tr[u].r >> 1;
    int res = 0;
    if(l<=mid) res += query(u<<1,l,r,f);
    if(r>mid) res += query(u<<1|1,l,r,f);
    return res;
}

int main()
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    while(m--)
    {
        int op,l,r;scanf("%d%d%d",&op,&l,&r);
        if(op==1) modify(1,l,0),modify(1,r,1);
        else printf("%d\n",query(1,1,r,0) - query(1,1,l-1,1));
    }
    return 0;
}

本文作者:艾特玖

本文链接:https://www.cnblogs.com/aitejiu/p/16220080.html

版权声明:本作品采用艾特玖许可协议进行许可。

posted @   艾特玖  阅读(34)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起