• [APIO2018] New Home 新家


    扫描线+线段树+二分答案+set+STL

    就是把区间数颜色做得很好

    时间看成线段,扫描线

    对于某一个询问位置x

    二分答案转化,看区间内有没有k种颜色。。

    一个区间数颜色的套路是,prei上一个该颜色出现位置

    查[x-mid,x+mid]pre小于x-mid的有几个。

    树套树!!(TLE飞起)

    其实并不关心是哪些个,只关心是否有k种

    对于(prei,i)开区间,一定没有i这个颜色

    所以,查找[mid+1,U]的最小值,如果在x-mid左边,那么就不行!加上二分两个logn

    维护pre,开k个multiset

    还有一些颜色,坐标最大的出现位置在x的左边,二分并不会考虑到

    全局维护一个multiset(堆也可以),里面放每个颜色的最右边的点出现位置,查询最小值,这个最小值和二分的答案取min

    还可以线段树上二分

    一个logn这题的一个log做法

    恶心之处是:

    1.同一时间,同一位置,会有相同的颜色,,:暴力提前把每种颜色能合并的都合并!(否则前驱后继太难找)

    2.同一时间,同一位置,会有不同的颜色,,:每个叶子维护一个懒惰删除小根堆,

    3.没有前驱,必须插入一个-inf,空节点,t[0].mi=inf

    代码:

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    #define mid ((l+r)>>1)
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=3e5+5;
    const int inf=0x3f3f3f3f;
    int n,k,q;
    struct item{
        int l,r,x,co;
        bool friend operator <(item a,item b){
            if(a.x!=b.x) return a.x<b.x;
            if(a.l!=b.l)return a.l<b.l;
            return a.r<b.r;
        }
    }lp[N];
    vector<int>mem[N];
    int exi[N],m;
    int U;
    struct heap{
        priority_queue<int,vector<int>,greater<int> >h,d;
        void push(int v){h.push(v);}
        int top(){
            while(!d.empty()&&!h.empty()&&(d.top()==h.top())) d.pop(),h.pop();
            if(!h.empty()) return h.top();
            return inf;
        }
        void dele(int v){d.push(v);}
    }hp[N];
    int cnt;
    
    struct Set{
        multiset<int>st;
        multiset<int>::iterator it;
        int bac(int v){
            it=st.upper_bound(v);
            if(it!=st.end()) return *it;
            return inf;
        }
        int pre(int v){
            it=st.lower_bound(v);
            if(it!=st.begin()) return *(--it);
            return -inf;
        }
        void ins(int v){st.insert(v);}
        void dele(int v){
            it=st.find(v);st.erase(it);
        }
        int big(){
            if(st.empty()) return -inf;
            it=st.end();--it;return *it;
        }
        int smal(){
            return *st.begin();
        }
    }s[N];
    
    struct node{
        int ls,rs;
        int num;//numth of hp;
        int mi;
    }t[N*80];
    int rt;
    int tot;
    void pushup(int x){
        t[x].mi=min(t[t[x].ls].mi,t[t[x].rs].mi);
    }
    void dele(int x,int l,int r,int p,int c){
        if(l==r){
            hp[t[x].num].dele(c);
            t[x].mi=hp[t[x].num].top();
        //    cout<<" upda "<<l<<" "<<t[x].mi<<endl;
            return;
        }
        if(p<=mid) dele(t[x].ls,l,mid,p,c);
        else dele(t[x].rs,mid+1,r,p,c);
        pushup(x);
    }
    void ins(int &x,int l,int r,int p,int c){
        if(!x) x=++tot;
        if(l==r){
            if(!t[x].num) t[x].num=++cnt;
            hp[t[x].num].push(c);
            t[x].mi=hp[t[x].num].top();
        //    cout<<" upda "<<l<<" "<<t[x].mi<<endl;
            return;
        }
        if(p<=mid) ins(t[x].ls,l,mid,p,c);
        else ins(t[x].rs,mid+1,r,p,c);
        pushup(x);
    }
    int query(int x,int l,int r,int L,int R){
    //    cout<<" query "<<x<<" "<<l<<" "<<r<<" : "<<L<<" "<<R<<" "<<t[x].mi<<endl;
        if(L>U) return inf;
        if(!x) return inf;
        if(L<=l&&r<=R) return t[x].mi;
        int ret=inf;
        if(L<=mid) ret=min(ret,query(t[x].ls,l,mid,L,R));
        if(mid<R) ret=min(ret,query(t[x].rs,mid+1,r,L,R));
        return ret;
    }
    int check(int pos){
        int l=pos,r=U;
        int ret=0;
    //    cout<<" check "<<pos<<endl;
        while(l<=r){
        //    cout<<l<<" "<<r<<" "<<mid<<endl;
            int mi=query(rt,1,U,mid+1,inf);
            if(mi+mid>=2*pos) ret=mid,r=mid-1;
            else l=mid+1;
        }
        return ret;
    }
    
    struct question{//0:dele 1:add 2:query
        int typ;
        int co,pos,id;
        int tim;
        bool friend operator<(question a,question b){
            if(a.tim!=b.tim) return a.tim<b.tim;
            return a.typ<b.typ;
        }
    }que[N*2+N];
    int ans[N];
    int main(){
        rd(n);rd(k);rd(q);
        int tot=0;
        int xi,ti,ai,bi;
        t[0].mi=inf;
        for(reg i=1;i<=n;++i){
            rd(xi);rd(ti);rd(ai);rd(bi);
            lp[i].x=xi;lp[i].co=ti;lp[i].l=ai;lp[i].r=bi;
        }
        sort(lp+1,lp+n+1);
        for(reg i=1;i<=n;++i){
            mem[lp[i].co].push_back(i);
        }
        for(reg i=1;i<=k;++i){
        //    cout<<" ----------------------------------------co "<<i<<" sz "<<mem[i].size()<<endl;
            for(reg j=0;j<mem[i].size();++j){
                //cout<<" pos "<<lp[mem[i][j]].x<<" : "<<lp[mem[i][j]].l<<" "<<lp[mem[i][j]].r<<endl;
                int now=mem[i][j];
                while(j+1<mem[i].size()&&lp[now].x==lp[mem[i][j+1]].x&&lp[now].r+1>=lp[mem[i][j+1]].l){
                    lp[now].r=max(lp[now].r,lp[mem[i][j+1]].r);
                    ++j;
                }
                exi[++m]=now;
            }
        }
        for(reg i=1;i<=m;++i){
            ti=lp[exi[i]].co;xi=lp[exi[i]].x;ai=lp[exi[i]].l;bi=lp[exi[i]].r;
            que[++tot].typ=1;que[tot].co=ti;que[tot].pos=xi;
            que[tot].tim=ai;
            
            que[++tot].typ=0;que[tot].co=ti;que[tot].pos=xi;
            que[tot].tim=bi+1;
            U=max(U,xi);
        }
        for(reg i=1;i<=q;++i){
            rd(xi);rd(ti);
            que[++tot].typ=2;
            que[tot].id=i;que[tot].pos=xi;que[tot].tim=ti;    
            U=max(U,xi);
        }
        sort(que+1,que+tot+1);
        for(reg i=1;i<=tot;++i){
            if(que[i].typ==0){
                int co=que[i].co;
                int pos=que[i].pos;
                int big=s[co].big();
                s[k+1].dele(big);
                
                int bc=s[co].bac(pos);
                int pr=s[co].pre(pos);
                if(bc!=inf){
                    dele(rt,1,U,bc,pos);
                    
                    ins(rt,1,U,bc,pr);
                }
                dele(rt,1,U,pos,pr);
                ins(rt,1,U,pos,inf);
                
                s[co].dele(pos);
                big=s[co].big();
                if(big!=-inf){
                    s[k+1].ins(big);
                }
            }else if(que[i].typ==1){
                int co=que[i].co;
                int pos=que[i].pos;
                if(s[co].st.empty()){
                    s[co].ins(pos);
                    s[k+1].ins(pos);
                    int pr=-inf;
                    ins(rt,1,U,pos,pr);
                }else{
                    int big=s[co].big();
                    s[k+1].dele(big);
                    int pr=s[co].pre(pos);
                    ins(rt,1,U,pos,pr);
                    int bc=s[co].bac(pos);
                    if(bc!=inf){
                        dele(rt,1,U,bc,pr);
                        ins(rt,1,U,bc,pos);
                    }
    //                }else{
    //                    int bc=s[co].bac(pos);
    //                    if(bc!=inf){
    //                        
    //                    }
    //                }
    //                
                    s[co].ins(pos);
                    big=s[co].big();
                    if(big!=-inf){
                        s[k+1].ins(big);
                    }
                }
                
            }else{
                int pos=que[i].pos;
                //cout<<" pos "<<pos<<" ii "<<i<<endl;
                if((int)s[k+1].st.size()<k){
                    ans[que[i].id]=-1;
                }else{
                    int smal=s[k+1].smal();
                    //cout<<" smal "<<smal<<endl;
                    int dis=max(pos-smal,0);
                //    cout<<" dis "<<dis<<endl;
                    int far=check(pos);
                //    cout<<" far "<<far<<endl;
                    ans[que[i].id]=max(far-pos,dis);
                }
            }
        }
        for(reg i=1;i<=q;++i){
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/23 10:47:16
    */
  • 相关阅读:
    【转】在Ubuntu上下载、编译和安装Android最新源代码
    【转】Linux(ubuntu14.04)上编译Android4.4源码的环境搭建及编译全过程
    linux kernel API and google android compile guide
    【转】如何单独编译Android源代码中的模块--不错
    【转】Android源代码编译命令m/mm/mmm/make分析--不错
    【转】linux设备驱动之MMC SD卡——核心层简单分析
    DELL笔记本拆机添加内存条
    【转】windows7 64位系统认不出8g内存显示只有3G可用
    matlab 神经网络工具箱的实用
    学习算法收敛条件的判断
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10422877.html
Copyright © 2020-2023  润新知