[APIO2018] New Home 新家 題解
阿新 • • 發佈:2020-11-24
[APIO2018] New Home 新家 題解
首先將時間離散化,然後依據時間建一棵線段樹。將每一個店開業歇業時間搞到樹上。
這樣問題就轉化為:有一個數軸每次加入或刪除一個點。每一個點有一個顏色。在任意時間詢問某一個點距離某一種顏色的最遠距離。到某一個顏色的距離為到這個顏色的點的最小距離。
顯然可以二分答案。每次詢問區間\([l,r]\)是否包含了所有顏色的點。
對於每一個顏色我們搞一個set。記錄每一個點到前面的那個同色的點,也就是前驅,記為pre[i]。
這個玩意的充要條件是在區間\([l,\infty]\) 的pre[i]都滿足>=r。
對於這個我們也可以將座標離散化搞到一個樹上。
時間複雜度是\(O(N\times \log ^2 N)\)
這題也有單log的做法,就是線上段樹上二分的地方的優化,不想多講。
code:
(這個程式碼被卡常了我也懶得改了)
#include<bits/stdc++.h> #define rb(a,b,c) for(int a=b;a<=c;++a) #define rl(a,b,c) for(int a=b;a>=c;--a) #define LL long long #define IT iterator #define PB push_back #define II(a,b) make_pair(a,b) #define FIR first #define SEC second #define FREO freopen("check.out","w",stdout) #define rep(a,b) for(int a=0;a<b;++a) #define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()) #define random(a) rng()%a #define ALL(a) a.begin(),a.end() #define POB pop_back #define ff fflush(stdout) #define fastio ios::sync_with_stdio(false) #define check_min(a,b) a=min(a,b) #define check_max(a,b) a=max(a,b) using namespace std; inline int read() { int num = 0, f = 1; char ch = getchar(); while( !isdigit( ch ) ) { if(ch == '-') f = -1; ch = getchar(); } while( isdigit( ch ) ) num = (num << 3) + (num << 1) + (ch ^ 48), ch = getchar(); return num * f; } const int INF=0x3f3f3f3f; typedef pair<int,int> mp; /*} */ const int MAXN=6e5+20; int n,k,q; vector<mp> sor; vector<int> pos_; int x[MAXN],t[MAXN],a[MAXN],b[MAXN],l[MAXN],y[MAXN]; map<int,int> M; int find(int f){ //第一個>=f的位置 return lower_bound(ALL(pos_),f)-pos_.begin()+1; } const int N=1<<20; int rest[MAXN]; struct SEGMENTTREE{ int tree[N+N];//最小 SEGMENTTREE(){ memset(tree,63,sizeof(tree)); } void modify(int index,int val){ index+=N-1; tree[index]=val; index>>=1; while(index){ tree[index]=min(tree[index<<1],tree[index<<1|1]); index>>=1; } } int query(int a,int b,int now=1,int l=1,int r=N+1){ if(r<=a||l>=b){ return INF; } if(r<=b&&l>=a){ return tree[now]; } int mid=(l+r)>>1; return min(query(a,b,now<<1,l,mid),query(a,b,now<<1|1,mid,r)); } }sgt; set<int> pos[MAXN]; void add(int x_,int t_){ pos[t_].insert(x_); auto ite=pos[t_].upper_bound(x_); if(ite!=pos[t_].end()){ sgt.modify(*ite,x_); } ite=pos[t_].lower_bound(x_); if(ite!=pos[t_].begin()){ ite--; sgt.modify(x_,*ite); } else { sgt.modify(x_,-INF); } } void del(int x_,int t_){ sgt.modify(x_,INF); pos[t_].erase(x_); auto ite=pos[t_].upper_bound(x_); if(ite==pos[t_].end()) return; if(ite==pos[t_].begin()){ sgt.modify(*ite,-INF); } else{ int z=*ite; ite--; sgt.modify(z,*ite); } } bool check(int x_,int dis){ int st=find(x_+dis+1); if(sgt.query(st,N+1)<find(x_-dis)) return 0; return 1; } struct EVENTSEGTREE{ vector<int> tree[N+N]; EVENTSEGTREE(){ } void add_event(int st,int ed,int val,int now=1,int l=1,int r=N+1){ if(r<=st||l>=ed){ return ; } if(r<=ed&&l>=st){ tree[now].PB(val); return ; } int mid=(l+r)>>1; add_event(st,ed,val,now<<1,l,mid); add_event(st,ed,val,now<<1|1,mid,r); } void run(int now=1,int l_=1,int r_=N+1){ for(auto it:tree[now]){ if(it>0){ add(x[it],t[it]); } } if(l_==r_-1){ for(auto it:tree[now]){ if(it<0){ int lb=0,rb=1e8+1; if(!check(l[-it],rb)){ rest[-it]=-1; } else{ while(lb<rb){ int mid=(lb+rb)>>1; if(check(l[-it],mid)) rb=mid; else lb=mid+1; } rest[-it]=lb; } } } } else{ int mid=(l_+r_)>>1; run(now<<1,l_,mid); run(now<<1|1,mid,r_); } for(auto it:tree[now]){ if(it>0){ del(x[it],t[it]); } } } }esgt; int main(){ // scanf("%d%d%d",&n,&k,&q); n=read(); k=read(); q=read(); rb(i,1,n){ int xi,ti,ai,bi; // scanf("%d%d%d%d",&xi,&ti,&ai,&bi); xi=read(); ti=read(); ai=read(); bi=read(); a[i]=ai; b[i]=bi; M[ai]=M[bi]=1; t[i]=ti; sor.PB(II(xi,i)); } rb(i,1,q){ l[i]=read(); y[i]=read(); } rb(i,1,q){ // scanf("%d%d",&l[i],&y[i]); M[y[i]]=1; } rb(i,1,k){ n++; a[n]=-INF; b[n]=INF; M[a[n]]=M[b[n]]=1; x[n]=INF; t[n]=i; sor.PB(II(x[n],n)); } sort(ALL(sor)); rep(i,n){ x[sor[i].SEC]=i+1; pos_.PB(sor[i].FIR); } int cnt=0; for(auto ite=M.begin();ite!=M.end();ite++){ ite->SEC=++cnt; } rb(i,1,n){ a[i]=M[a[i]]; b[i]=M[b[i]]; esgt.add_event(a[i],b[i]+1,i); } rb(i,1,q){ y[i]=M[y[i]]; esgt.add_event(y[i],y[i]+1,-i); } esgt.run(); rb(i,1,q){ printf("%d\n",rest[i]); } return 0; }