CSU - 2170 千万别用树套树 (线段树)

题目链接:CSU 2170

 

题目大意:[1,n]的区间进行q次操作.有下面2种类型

  • 1:添加一条[l,r]的线段
  • 2:查询可以完全覆盖[l,r]区间的线段有多少条

需要注意的是查询区间  r-l<=2

 

分析:

这么一个水题之前和队友想了一天都没想出来.今天又看了这道题,才发现还有个查询区间 r-l<=2  的条件. emmm,没漏看条件的话这题还是很好写的.维护下区间内左右端点的个数,减下就能出来了. r-l==2 的话加上重复减的就是答案了.

 

以下是代码:

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

#define Fi first
#define Se second
#define ll long long
#define inf 0x3f3f3f3f
#define lowbit(x) (x&-x)
#define PLL pair<ll,ll>
#define PII pair<int,int>
#define in(b) scanf("%d",&b)
#define l_inf 0x3f3f3f3f3f3f3f
#define mmin(a,b,c) min(a,min(b,c))
#define mmax(a,b,c) max(a,max(b,c))
#define debug(a) cout<<#a<<"="<<a<<endl;
#define debug2(a,b) cout<<#a<<"="<<a<<" "<<#b<<"="<<b<<endl;
using namespace std;
const int N=1e5+10;
int cnt[N],s1[N<<2],s2[N<<2];
void update(int l,int r,int p,int k,int tr[])
{
    if(l==r)
    {
        tr[k]++;
        return ;
    }
    int m=(l+r)>>1;
    if(p<=m) update(l,m,p,k<<1,tr);
    else update(m+1,r,p,k<<1|1,tr);
    tr[k]=tr[k<<1]+tr[k<<1|1];
}
int query(int l,int r,int L,int R,int k,int tr[])
{
    if(l>=L&&r<=R)
    {
        return tr[k];
    }
    if(l==r) return 0;
    int m=(l+r)>>1;
    int ans=0;
    if(L<=m) ans+=query(l,m,L,R,k<<1,tr);
    if(R>m) ans+=query(m+1,r,L,R,k<<1|1,tr);
    return ans;
}

int main()
{
    int n,q;
    while(~scanf("%d%d",&n,&q))
    {
        int sta,l,r,ss=0;
        memset(s1,0,sizeof s1);
        memset(s2,0,sizeof s2);
        memset(cnt,0,sizeof cnt);
        while(q--)
        {
            scanf("%d%d%d",&sta,&l,&r);
            if(sta==1)
            {
                ss++;
                if(l==r) cnt[l]+=2;
                update(1,n,l,1,s1);
                update(1,n,r,1,s2);
            }
            else
            {
                int l1,r1,l2,r2;
                l1=1;r1=r-1;
                l2=l+1;r2=n;
                int ans=ss;
                if(l1<=r1) ans-=query(1,n,l1,r1,1,s2);
                if(l2<=r2) ans-=query(1,n,l2,r2,1,s1);
                if(r-l==2) ans+=cnt[l+1];
                printf("%d\n",ans);
            }
        }

    }
    return 0;
}
/*
4 3
1 1 4
1 3 3
2 2 4
*/

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值