ACdream - 1157 Segments

题目:

由3钟类型操作:
1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]
2)C i (1-base) 删除第i条增加的线段,保证每条插入线段最多插入一次,且这次删除操作一定合法
3) Q L R(1 <= L <= R <= 1000000000) 查询目前存在的线段中有多少条线段完全包含[L,R]这个线段,线段X被线段Y完全包含即LY <= LX<= RX <= RY)
给出N,接下来N行,每行是3种类型之一

思路:时间为第一位分治,然后用左区间去更新右区间

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define PI acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
// 0x3f3f3f3f

const int maxn=100050;
struct Node{
    int type,x,y,id;
}q[maxn];
struct BIT{
    int n,b[2*maxn];
    void init(int _n){
        n=_n;
    }
    void add(int i,int val){
        for(;i<=n;i+=i&(-i))
            b[i]+=val;
    }
    int sum(int i){
        int ret=0;
        for(;i>0;i-=i&(-i))
            ret+=b[i];
        return ret;
    }
}bit;
int ans[maxn],vis[maxn];
int x[2*maxn],siz;
bool cmp1(const Node &a,const Node &b){
    return a.id<b.id;
}
bool cmp2(const Node &a,const Node &b){
    if(a.x!=b.x) return a.x<b.x;
    if(a.y!=b.y) a.y>b.y;
    return a.id<b.id;
}
void cdq(int L,int R){
    if(L>=R) return;
    int mid=(L+R)>>1;
    cdq(L,mid);
    cdq(mid+1,R);
    sort(q+L,q+R+1,cmp2);
    for(int i=L;i<=R;i++){
        if(q[i].id<=mid){
            if(q[i].type==1) bit.add(q[i].y,1);
            else if(q[i].type==2) bit.add(q[i].y,-1);
        }
        else{
            if(q[i].type==3)
                ans[q[i].id]+=bit.sum(siz)-bit.sum(q[i].y-1);
        }
    }
    for(int i=L;i<=R;i++){
        if(q[i].id<=mid){
            if(q[i].type==1) bit.add(q[i].y,-1);
            else if(q[i].type==2) bit.add(q[i].y,1);
        }
    }

}
int L[maxn],R[maxn],tot;
int main(){

//    freopen("D:\\input.txt","r",stdin);
//    freopen("D:\\output.txt","w",stdout);
    int n,pos;
    char str[10];
    while(~scanf("%d",&n)){
        tot=siz=0;
        mm(vis,0);
        mm(ans,0);
        for(int i=1;i<=n;i++){
            scanf("%s",str);
            if(str[0]=='D'){
                tot++;
                scanf("%d%d",&L[tot],&R[tot]);
                x[++siz]=L[tot];
                x[++siz]=R[tot];
                q[i].type=1;
                q[i].x=L[tot];
                q[i].y=R[tot];
                q[i].id=i;
            }
            else if(str[0]=='C'){
                scanf("%d",&pos);
                q[i].type=2;
                q[i].x=L[pos];
                q[i].y=R[pos];
                q[i].id=i;
            }
            else{
                vis[i]=1;
                scanf("%d%d",&q[i].x,&q[i].y);
                q[i].type=3;
                q[i].id=i;
                x[++siz]=q[i].x;
                x[++siz]=q[i].y;
            }
        }
        sort(x+1,x+siz+1);
        siz=unique(x+1,x+siz+1)-x-1;
        for(int i=1;i<=n;i++){
            q[i].x=lower_bound(x+1,x+siz+1,q[i].x)-x;
            q[i].y=lower_bound(x+1,x+siz+1,q[i].y)-x;
        }
        bit.init(siz);
        cdq(1,n);
        for(int i=1;i<=n;i++)
            if(vis[i])
                printf("%d\n",ans[i]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值