[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\n",ans[i]); } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/2/23 10:47:16 */