CQUOJ 24918 覆盖次数(树状数组)

http://acm.cqu.edu.cn:8888/oj/problem_show.php?pid=24918
这题是问你对于每次加进去的线段,他能完全覆盖多少条线段。
然后每次给的线段的长度都是递增的,但是这题有删除的操作,不然所有的保存下来,然后按照一个端点排序另外个端点查询就行了QAQ
于是这题就要用不同的姿势,首先可以画图看出来,能被他覆盖的线段,那肯定是左右端点都被覆盖,那么不能被覆盖的,肯定左右端点有一个没有被覆盖,这就是这题的性质,因为长度递增,所以不可能有线段两个端点都在加入的线段端点两侧。
所以可以一个树状数组维护右端点,一个维护左端点,然后查询的时候看在右端点右边的有几个,左端点左边的有几个,然后减去就行了。


代码:

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")

using namespace std;
#define   MAX           100005
#define   MAXN          6005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
//const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
    char c;
    while((c=getchar())<'0' || c>'9');
    x=c-'0';
    while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/

int op[MAX],b[MAX];
int line[MAX];
int xx[MAX*2];
int c[MAX*2];
int d[MAX*2];
int tot;
int sumf(int x){
    int ret=0;
    while(x){
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}
int sums(int x){
    int ret=0;
    while(x){
        ret+=d[x];
        x-=lowbit(x);
    }
    return ret;
}

void addf(int x,int v){
    while(x<=tot){
        c[x]+=v;
        x+=lowbit(x);
    }
}

void adds(int x,int v){
    while(x<=tot){
        d[x]+=v;
        x+=lowbit(x);
    }
}
int main(){
    //freopen("2.in","r",stdin);
    //freopen("3.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int num=0;
        int numl=0;
        mem(c,0);mem(d,0);
        for(int i=1;i<=n;i++){
            scanf("%d%d",&op[i],&b[i]);
            if(op[i]==0){
                line[++numl]=b[i];
                xx[num++]=b[i];
                xx[num++]=b[i]+numl;
            }
        }
        sort(xx,xx+num);
        tot=unique(xx,xx+num)-xx;
        int numm=0;
        int numj=0;
        for(int i=1;i<=n;i++){
            if(op[i]==0){
                numm++;
                int l=lower_bound(xx,xx+tot,b[i])-xx+1;
                int r=lower_bound(xx,xx+tot,b[i]+numm)-xx+1;
                int ans=numm-sumf(l-1)-(sums(tot)-sums(r))-1-numj;
                addf(l,1);
                adds(r,1);
                //cout<<l<<" "<<r<<endl;
                printf("%d\n",ans);
            }
            else{
                numj++;
                //cout<<line[b[i]]<<" "<<line[b[i]]+b[i]<<endl;
                int l=lower_bound(xx,xx+tot,line[b[i]])-xx+1;
                int r=lower_bound(xx,xx+tot,line[b[i]]+b[i])-xx+1;
                //cout<<l<<" "<<r<<endl;
                addf(l,-1);
                adds(r,-1);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值