zoukankan      html  css  js  c++  java
  • 【loj2585】【APIO2018】新家

    题目

    一条街上有(n) 个点,坐标为(x_i) , 店的种类为(t_i) , 开业时间为 ([a_i,b_i]) ;

    定义一种类型到一个点的距离为这种类的点到这个点的最近距离 ;

    定义一个点的不方便度为此时所有所有种类的店离这个点的距离的最大值(种类不足直接为-1);

    给出种类总数和询问数 (m) , 回答在 (y_j) 时间下,位置 (l_j) 的不方便度 ;

    $1 le n , q le 3 imes 10^5 , 1 le k le n $

    $ 1 le x_i,a_i,b_i le 10^9 , 1 le t_i le k , a_i le b_i $

    $1 le l_i , y_i le 10^8 $

    题解

    • 对时间做扫描线,只需要维护支持加入和删除点的查询;

    • 二分答案,考虑在$ [ x - mid , x + mid] $中间是否存在所有颜色的点;

    • (set) 维护每种颜色的前驱pre,条件转化成: ((x+mid,inf))(mn { pre } ge x - mid)

    • 为了方便你可以设置一个-inf点和inf点,并把所有颜色都先分别扔一个到inf和-inf上 ;

    • 用线段树套堆就可以做到$n log^2 n $ , 在线段树里面二分 (x+ans) 的位置即可做到 $n log n $ ;

    //很清新的数据结构;
    #include<bits/stdc++.h>
    #define inf (1e9 + 1)
    using namespace std;
    const int N=300010;
    int n,K,q,tot,cnt,ans[N];
    multiset<int>s[N],ss[N*64];
    multiset<int>::iterator it,itt;
    int rt,mn[N*64],ls[N*64],rs[N*64],sz;
    struct data{
    	int x,c,t,op;
    	bool operator <(const data&A)const{return t==A.t?op<A.op:t<A.t;}
    }A[N<<2];
    char gc(){
    	static char*p1,*p2,S[1000000];
    	if(p1==p2)p2=(p1=S)+fread(S,1,1000000,stdin);
    	return(p1==p2)?EOF:*p1++;
    }
    int rd(){
    	int x=0;char c=gc();
    	while(c<'0'||c>'9')c=gc();
    	while(c>='0'&&c<='9')x=x*10+c-'0',c=gc();
    	return x;
    }
    void update(int&k,int l,int r,int x,int add,int del){
    	if(!k)k=++sz;
    	if(l==r){
    		if(~add)ss[k].insert(add);
    		if(~del)ss[k].erase(ss[k].find(del));
    		mn[k]=ss[k].empty() ? inf : *ss[k].begin();//
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid)update(ls[k],l,mid,x,add,del);
    	else if(x>mid)update(rs[k],mid+1,r,x,add,del);
    	mn[k]=min(mn[ls[k]],mn[rs[k]]);
    }
    int query(int x){
    	int k=rt,l=1,r=inf,mnv=inf;//
    	while(l<r){
    		int mid=(l+r)>>1,tmp=min(mnv,mn[rs[k]]);
    		if(mid>=x&&tmp>=2*x-mid)k=ls[k],r=mid,mnv=tmp;
    		else k=rs[k],l=mid+1;
    	}
    	return l - x;
    }
    int main(){
    //	freopen("A.in","r",stdin);
    //	freopen("A.out","w",stdout);
    	n=rd();K=rd();q=rd();mn[0]=inf;//
    	for(int i=1;i<=K;++i)s[i].insert(-inf),s[i].insert(inf);//
    	for(int i=1;i<=n;++i){
    		int x=rd(),t=rd(),a=rd(),b=rd();
    		A[++tot]=(data){x,t,a,0};
    		A[++tot]=(data){x,t,b+1,1};
    	}
    	for(int i=1;i<=q;++i){
    		int l=rd(),y=rd();
    		A[++tot]=(data){l,i,y,2};
    	}
    	sort(A+1,A+tot+1);
    	for(int i=1;i<=K;++i)update(rt,1,inf,inf,-inf,-1);//
    	for(int i=1;i<=tot;++i){
    		int opt=A[i].op,c=A[i].c,x=A[i].x;
    		if(!opt){
    			it=itt=s[c].upper_bound(x);--itt;
    			update(rt,1,inf,*it,x,*itt);
    			update(rt,1,inf,x,*itt,-1);
    			if(s[c].size()==2)cnt++;
    			s[c].insert(x);
    		}else if(opt&1){
    			it=itt=s[c].upper_bound(x);--itt;--itt;
    			update(rt,1,inf,x,-1,*itt);
    			update(rt,1,inf,*it,*itt,x);
    			s[c].erase(++itt);
    			if(s[c].size()==2)cnt--;
    		}else ans[c]=cnt<K?-1:query(x);
    	}
    	for(int i=1;i<=q;++i)printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    我的暑假周记2018.7.21
    大道至简读后感
    我的暑假周记2018.7.15
    继承与多态
    java联级调用
    古罗马凯撒大帝字串加密
    作业三
    线性同余法产生1000个随机数
    Text2
    java登录界面
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10793238.html
Copyright © 2011-2022 走看看