zoukankan      html  css  js  c++  java
  • The Stream of Corning 2( 权值线段树/(树状数组+二分) )

    题意:

    有两种操作:1.在[l,r]上插入一条值为val的线段 2.问p位置上值第k小的线段的值(是否存在)

    特别的,询问的时候l和p合起来是一个递增序列

    1<=l,r<=1e9;1<=val<=1e6; 1<=k<=1e9

    思路:

    因为l和p总体是递增的,第i个询问的p一定大于i之前所有操作的l,而前面能影响到i的答案的只有r>=p的线段。由此可以想到将l,r,p合起来离散化,从左往右扫描,遇到l,就在权值线段树上插入对应的val,遇到r就删除对应的val,而遇到询问时,当前的线段树必然对应了P点的所有线段,求一下全局第k小就能得到答案。

    全局第k小除了利用权值线段树外,还能通过二分树状数组求得,复杂度比线段树多logn,但是实际测试好像还是树状数组快。

    权值线段树

    #include <bits/stdc++.h>
    #define lson  rt<<1
    #define rson rt<<1|1
    using namespace std;
    const int maxn=2e5+5;//离散化值可能有两倍
    struct node {
        int opt,p,val,id;
        operator<(node b) {
            if(p!=b.p)
                return p<b.p;
            else if(opt==2)
                return true;
            else if(b.opt==2)
                return false;
            else
                return id<b.id;
        }
    } P[maxn];
    int cnt=0,n;
    int T[maxn<<2];
    inline void push_now(int k){
        T[k]=T[k<<1]+T[k<<1|1];
    }
    void add(int rt,int l,int r,int p,int val){//[l,r]
        if(l==r){
            T[rt]+=val;
            return;
        }
        int mid=(l+r)>>1;
        if(p<=mid) add(lson,l,mid,p,val);
        if(p>mid) add(rson,mid+1,r,p,val);
        push_now(rt);
    }
    int query(int rt,int l,int r,int k){
        if(T[rt]<k) return -1;
        if(l==r) return l;
        int mid=(l+r)>>1;
        if(T[lson]>=k)
            return query(lson,l,mid,k);
        else
            return query(rson,mid+1,r,k-T[lson]);
    }
    int lisan[maxn],tot=0;
    int ans[maxn],acnt=0;
    int main() {
        int t,E;
        cin>>t;
        for(int kase=1; kase<=t; kase++) {
            scanf("%d",&E);
            tot=0;acnt=0;cnt=0;
            for(int i=1; i<=E; i++)
                T[i]=0;
            int x,val,y,opt;
            for(int i=1; i<=E; i++) {
                scanf("%d%d%d",&opt,&x,&val);
                if(opt==1) {
                    lisan[++tot]=val;
                    scanf("%d",&y);
                    P[++cnt]= {1,x,val,i};
                    P[++cnt]= {-1,y,val,i};
                } else {
                    P[++cnt]= {2,x,val,i};
                }
            }
            sort(lisan+1,lisan+1+tot);
            n=unique(lisan+1,lisan+1+tot)-(lisan+1);
            for(int i=1; i<=cnt; i++) {
                if(P[i].opt!=2)
                    P[i].val=lower_bound(lisan+1,lisan+1+n,P[i].val)-lisan;
            }
            sort(P+1,P+1+cnt);
            for(int i=1; i<=cnt; i++) {
                if(P[i].opt!=2) {
                    add(1,1,n,P[i].val,P[i].opt);
                }
                else {
                    int temp=query(1,1,n,P[i].val);
                    if(temp==-1)
                        ans[++acnt]=-1;
                    else
                        ans[++acnt]=lisan[temp];
                }
            }
            printf("Case %d:
    ",kase);
            for(int i=1; i<=acnt; i++) {
                printf("%d
    ",ans[i]);
            }
        }
    }
    

    树状数组+二分

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+5;//离散化值可能有两倍
    struct node {
        int opt,p,val,id;
        operator<(node b) {
            if(p!=b.p)
                return p<b.p;
            else if(opt==2)
                return true;
            else if(b.opt==2)
                return false;
            else
                return id<b.id;
        }
    } P[maxn];
    int cnt=0,n;
    int T[maxn];
    int lowbit(int x) {
        return x&(-x);
    }
    int getsum(int p) {
        int res=0;
        while(p>0) {
            res+=T[p];
            p-=lowbit(p);
        }
        return res;
    }
    void add(int p,int val) {
        while(p<=n) {
            T[p]+=val;
            p+=lowbit(p);
        }
    }
    int query(int x) {
        int l=0,r=n,mid;
        while(r-l>1) {
            mid=(r+l+1)/2;
            if(getsum(mid)>=x)
                r=mid;
            else
                l=mid;
        }
        return r;
    }
    int lisan[maxn],tot=0;
    int ans[maxn],acnt=0;
    int main() {
        int t,E;
        cin>>t;
        for(int kase=1; kase<=t; kase++) {
            scanf("%d",&E);
            tot=0;
            acnt=0;
            cnt=0;
            for(int i=1; i<=E; i++)
                T[i]=0;
            int x,val,y,opt;
            for(int i=1; i<=E; i++) {
                scanf("%d%d%d",&opt,&x,&val);
                if(opt==1) {
                    lisan[++tot]=val;
                    scanf("%d",&y);
                    P[++cnt]= {1,x,val,i};
                    P[++cnt]= {-1,y,val,i};
                } else {
                    P[++cnt]= {2,x,val,i};
                }
            }
            sort(lisan+1,lisan+1+tot);
            n=unique(lisan+1,lisan+1+tot)-(lisan+1);
            for(int i=1; i<=cnt; i++) {
                if(P[i].opt!=2)
                    P[i].val=lower_bound(lisan+1,lisan+1+n,P[i].val)-lisan;
            }
            sort(P+1,P+1+cnt);
            for(int i=1; i<=cnt; i++) {
                if(P[i].opt!=2) {
                    add(P[i].val,P[i].opt);
                }
                else {
                    int temp=query(P[i].val);
                    if(getsum(n)<P[i].val)
                        ans[++acnt]=-1;
                    else
                        ans[++acnt]=lisan[temp];
                }
            }
            printf("Case %d:
    ",kase);
            for(int i=1; i<=acnt; i++) {
                printf("%d
    ",ans[i]);
            }
        }
    }
    
  • 相关阅读:
    cmd的有趣的操作
    Hbuilder 【App开发准备】
    Hbuilder 【app设置,云打包】
    U盘测试和查明真伪
    luogu P2962 [USACO09NOV]灯Lights 高斯消元
    Nowcoder牛客网NOIP赛前集训营-提高组(第六场)
    Codeforces Round #517 (Div. 2)
    code——tmp
    bzoj3329: Xorequ 数位DP
    bzoj3033: 太鼓达人 欧拉路径
  • 原文地址:https://www.cnblogs.com/ucprer/p/11644528.html
Copyright © 2011-2022 走看看