zoukankan      html  css  js  c++  java
  • ACdream 1157 Segments CDQ分治

    题目链接:https://vjudge.net/problem/ACdream-1157

    题意:

    Problem Description

    由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种类型之一

    Input

    多组数据,每组数据N

    接下来N行,每行是三种操作之一(1 <= N  <= 10^5)

    Output

    对于每个Q操作,输出一行,答案

    Sample Input

    6
    D 1 100
    D 3 8
    D 4 10
    Q 3 8
    C 1
    Q 3 8

    Sample Output

    2
    1

    Hint

    注意,删除第i条增加的线段,不是说第i行,而是说第i次增加。

    比如

    D 1 10

    Q 1 10

    D 2 3

    D 3 4

    Q 5 6

    D 5 6

    C 2是删除D 2 3

    C 4是删除D 5 6

    解法:CDQ分治,将删除操作看作插入一条数量为-1的线段,查询操作看作插入一条数量为0的线段,用cnt[i]表示第i次插入的线段被之前插入的线段包含的次数,按操作顺序进行分治,每次统计[l,mid+1]中有多少元素j满足j.y>=i.y,j.x<=i.x,其中mid+1<=i<=r,这个过程可以通过对两个区间都以x为第一关键字降序排,以y为第二关键字升序排,对于[mid+1,r]中的每个i(i为数量为0的元素,即为查询),将[l,mid]中所有满足j.y>=i.y的j以j.x为下标,cnt[j]为键值插入到树状数组中,那么每次只需统计树状数组中下标小于等于i.x的元素键值之和累加到cnt[i]中即可。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5+10;
    int n, h[maxn], tot;
    struct node{
        int x,y,cnt,id,ans;
        bool operator<(const node &rhs) const{
            if(y!=rhs.y)return y>rhs.y;
            return x<rhs.x;
        }
    }p[maxn],q[maxn];
    bool cmp(node a, node b){
        return a.id<b.id;
    }
    struct BIT{
        int b[maxn];
        void init(){
            memset(b, 0, sizeof(b));
        }
        inline int lowbit(int x){
            return (x&(-x));
        }
        void add(int x, int v){
            while(x<=tot){
                b[x]+=v;
                x+=lowbit(x);
            }
        }
        int query(int x){
            int ret = 0;
            while(x){
                ret += b[x];
                x -= lowbit(x);
            }
            return ret;
        }
    }bit;
    void CDQ(int l, int r){
        if(l == r) return;
        int mid = (l+r)/2;
        CDQ(l,mid);
        CDQ(mid+1,r);
        sort(p+l,p+mid+1);
        sort(p+mid+1,p+r+1);
        int j=l;
        for(int i=mid+1; i<=r; i++){
            for(;j<=mid&&p[j].y>=p[i].y;j++) bit.add(p[j].x, p[j].cnt);
            if(!p[i].cnt) p[i].ans+=bit.query(p[i].x);
        }
        for(int i=l; i<j; i++) bit.add(p[i].x, -p[i].cnt);
        merge(p+l,p+mid+1,p+mid+1,p+r+1,q);
        for(int i=0; i<r-l+1; i++) p[l+i]=q[i];
    }
    int res, l[maxn], r[maxn];
    
    int main()
    {
        while(~scanf("%d", &n))
        {
            bit.init();
            tot=0,res=1;
            for(int i=1; i<=n; i++){
                p[i].id = i, p[i].ans = 0;
                char op[3];
                scanf("%s", op);
                if(op[0] == 'D'){
                    scanf("%d%d",&p[i].x,&p[i].y);
                    p[i].cnt=1;
                    l[res]=p[i].x,r[res++]=p[i].y;
                    h[++tot]=p[i].x,h[++tot]=p[i].y;
                }
                else if(op[0]=='Q'){
                    scanf("%d%d",&p[i].x,&p[i].y);
                    p[i].cnt=0;
                    h[++tot]=p[i].x,h[++tot]=p[i].y;
                }
                else{
                    int temp;
                    scanf("%d", &temp);
                    p[i].x=l[temp],p[i].y=r[temp];
                    p[i].cnt=-1;
                }
            }
            sort(h+1,h+tot+1);
            tot = unique(h+1,h+tot+1)-h-1;
            for(int i=1; i<=n; i++){
                p[i].x=lower_bound(h+1,h+tot+1,p[i].x)-h;
                p[i].y=lower_bound(h+1,h+tot+1,p[i].y)-h;
            }
            CDQ(1, n);
            sort(p+1,p+n+1,cmp);
            for(int i=1; i<=n; i++){
                if(!p[i].cnt) printf("%d
    ", p[i].ans);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    变量和数据类型
    Manager 多进程之间的数据共享
    多进程之间的数据传输 Pipe
    多进程
    消费者 生产者
    queue 队列优先级
    Python 最难的问题
    threading 多线程
    线程进程概述
    倒计时器 小玩意
  • 原文地址:https://www.cnblogs.com/spfa/p/7359856.html
Copyright © 2011-2022 走看看