传送门:bzoj5462
题解
orzkczno1奆佬
这个
n
log
n
n\log n
nlogn的做法好妙呀(不想写线段树分治了
代码
#include<bits/stdc++.h>
#define fi first
#define sc second
#define pb push_back
//#define ccosi
using namespace std;
const int N=3e5+10,MX=1e9;
typedef long long ll;
typedef double db;
int n,K,m,cnt,ans[N];
int v[N],num,as;
struct qr{
int pos,typ,tim,op;
bool operator<(const qr&ky)const{
if(tim!=ky.tim) return tim<ky.tim;
return op<ky.op;
}
}a[N*3];
#ifndef ccosi
char buf[(1<<15)];int p1=0,p2=0;
inline char gc()
{
if(p1==p2) p1=0,p2=fread(buf,1,(1<<15),stdin);
return (p1==p2)?EOF:buf[p1++];
}
#endif
#ifdef ccosi
#define gc getchar
#endif
char cp;
template<class T>inline void rd(T &x)
{
cp=gc();x=0;int f=0;
for(;!isdigit(cp);cp=gc()) if(cp=='-') f=1;
for(;isdigit(cp);cp=gc()) x=x*10+(cp^48);
if(f) x=-x;
}
inline void prit(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) prit(x/10);putchar('0'+(x%10));
}
inline int fd(int x){return lower_bound(v+1,v+num,x)-v;}
int cot,exi[N];
multiset<int>t[N];
multiset<int>::iterator it,it1,it2;
namespace SGT{
#define lc k<<1
#define rc k<<1|1
#define mid ((l+r)>>1)
#define lcc lc,l,mid
#define rcc rc,mid+1,r
int n,mn[N<<2],mxv[N<<2],X,Y,Z;
struct Hp{
priority_queue<int,vector<int>,greater<int> >a,b;
inline void push(int x){a.push(x);}
inline void del(int x){b.push(x);}
inline int top(){
for(;(!b.empty()) && a.top()==b.top();a.pop(),b.pop());
return a.top();
}
}q[N];
void build(int k,int l,int r)
{
mn[k]=MX;
if(l==r) {mxv[k]=v[l];if(l==n) mn[k]=-MX;return;}
build(lcc);build(rcc);
mxv[k]=max(mxv[lc],mxv[rc]);mn[k]=min(mn[lc],mn[rc]);
}
inline void init(int n_)
{
n=n_;build(1,1,n);int i;
for(i=1;i<n;++i) q[i].push(MX);
for(i=1;i<=K;++i) q[n].push(-MX);//每种颜色都有一个前驱
}
void oo(int k,int l,int r,int op)
{
if(l==r){
if(op==0) q[l].del(Y);
else if(op==1) q[l].push(Y);
else q[l].del(Y),q[l].push(Z);
mn[k]=q[l].top();
return;
}
if(X<=mid) oo(lcc,op);else oo(rcc,op);
mn[k]=min(mn[lc],mn[rc]);
}
inline void add(int tp,int x)
{
exi[tp]++;if(exi[tp]==1) cot++;
it1=t[tp].insert(x);it2=it1;
--it1;++it2;
X=fd(x);Y=(*it1);oo(1,1,n,1);
X=fd(*it2);Y=(*it1);Z=x;oo(1,1,n,2);
}
inline void del(int tp,int x)
{
exi[tp]--;if(exi[tp]==0) cot--;
it=t[tp].find(x);it1=it;it2=it1;
--it1;++it2;
X=fd(x);Y=(*it1);oo(1,1,n,0);
X=fd(*it2);Y=x;Z=(*it1);oo(1,1,n,2);
t[tp].erase(it);
}
int ask(int k,int l,int r,int x,int &dr)
{
if(cot!=K) return -1;
if(l==r) {return min((x<<1)-min(dr,mn[k]),mxv[k])-x;}
if(x>mxv[lc]) return ask(rcc,x,dr);//x->non-LSH compared with mxv[lc] NOT mid
if(mxv[lc]+1+min(mn[rc],dr)<=(x<<1)) return ask(rcc,x,dr);
dr=min(mn[rc],dr);
return ask(lcc,x,dr);
}
}
int main(){
int i,j,x,y,c,d;
rd(n);rd(K);rd(m);
for(i=1;i<=n;++i){
rd(x);rd(y);rd(c);rd(d);v[i]=x;
a[++cnt]=(qr){x,y,c,-1};
a[++cnt]=(qr){x,y,d+1,-2};
}
sort(v+1,v+n+1);num=unique(v+1,v+n+1)-v-1;
v[++num]=MX<<1;//以防query中x>v[n] MX<<1-> min((x<<1)-min(dr,mn[k]),mxv[k]) 保证取min的是左侧
SGT::init(num);
for(i=1;i<=m;++i){
rd(x);rd(y);
a[++cnt]=(qr){x,0,y,i};
}
for(i=1;i<=K;++i) t[i].insert(MX),t[i].insert(-MX);
sort(a+1,a+cnt+1);
for(i=1;i<=cnt;++i){
if(a[i].op>0) ans[a[i].op]=SGT::ask(1,1,num,a[i].pos,(as=MX));
else if(a[i].op==-1) SGT::add(a[i].typ,a[i].pos);
else SGT::del(a[i].typ,a[i].pos);
}
for(i=1;i<=m;++i) {prit(ans[i]);if(i<m) putchar('\n');}
return 0;
}