[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
*/
原文地址:https://www.cnblogs.com/Miracevin/p/10422877.html