• CF765F Souvenirs


    Souvenirs

    给出 (n) 以及一个长为 (n) 的序列 (a)

    给出 (m),接下来 (m) 组询问。每组询问给出一个 (l,r),你需要求出,对于 (i,j in [l,r]),且满足 (i eq j)(|a_i-a_j|) 的最小值。

    (1 leq n leq 10^5)(1 leq m leq 3 imes 10^5)(0 leq a_i leq 10^9)

    题解

    https://www.cnblogs.com/CQzhangyu/p/8468825.html

    [a_{j'}-a_i< a_j-a_{j'}\ 2(a_{j'}-a_i)< a_j-a_i\ ]

    所以每次差会减半。

    怎么找 (a_j) 呢?按照从大到小的顺序插入线段树然后在线段树上二分即可。

    然后每个贡献可以写成点对的形式,就转化成了一个二维偏序。

    时间复杂度 (O(nlog nlog v))

    CO int N=1e5+10,inf=2e9;
    int a[N],o[N];
    
    namespace seg{
    	int s[4*N];
    
    	#define lc (x<<1)
    	#define rc (x<<1|1)
    	#define mid ((l+r)>>1)
    	void build(int x,int l,int r){
    		s[x]=inf;
    		if(l==r) return;
    		build(lc,l,mid),build(rc,mid+1,r);
    	}
    	void insert(int x,int l,int r,int p,int v){
    		s[x]=min(s[x],v);
    		if(l==r) return;
    		if(p<=mid) insert(lc,l,mid,p,v);
    		else insert(rc,mid+1,r,p,v);
    	}
    	int query(int x,int l,int r,int p,int v){
    		if(p<l) return 0;
    		if(r<=p){
    			if(s[x]>v) return 0;
    			if(l==r) return l;
    			if(s[rc]<=v) return query(rc,mid+1,r,p,v);
    			else return query(lc,l,mid,p,v);
    		}
    		if(p<=mid) return query(lc,l,mid,p,v);
    		int ans=query(rc,mid+1,r,p,v);
    		if(ans) return ans;
    		return query(lc,l,mid,p,v);
    	}
    	#undef lc
    	#undef rc
    	#undef mid
    }
    
    namespace bit{
    	int n,s[N];
    	
    	void init(int n){
    		bit::n=n,fill(s+1,s+n+1,inf);
    	}
    	#define lowbit(x) (x&-x)
    	void insert(int p,int v){
    		for(int i=p;i;i-=lowbit(i)) s[i]=min(s[i],v);
    	}
    	int query(int p){
    		int ans=inf;
    		for(int i=p;i<=n;i+=lowbit(i)) ans=min(ans,s[i]);
    		return ans;
    	}
    	#undef lowbit
    }
    
    struct point {int x,y,v;} p[N*30],q[3*N];
    int ans[3*N];
    
    void solve(int n,int m){
    	for(int i=1;i<=n;++i) o[i]=i;
    	sort(o+1,o+n+1,[](int i,int j)->bool{
    		return a[i]!=a[j]?a[i]>a[j]:i<j; // edit 1: i<j
    	});
    	seg::build(1,1,n);
    	int tot=0;
    	for(int i=1;i<=n;++i){
    		seg::insert(1,1,n,o[i],a[o[i]]);
    		int j=seg::query(1,1,n,o[i]-1,inf-1);
    		if(!j) continue;
    		do p[++tot]={j,o[i],a[j]-a[o[i]]};
    		while((j=seg::query(1,1,n,j-1,(a[o[i]]+a[j]+1)/2-1)));
    	}
    	sort(p+1,p+tot+1,[](CO point&a,CO point&b)->bool{
    		return a.y<b.y;
    	});
    	sort(q+1,q+m+1,[](CO point&a,CO point&b)->bool{
    		return a.y<b.y;
    	});
    	bit::init(n);
    	for(int i=1,j=1;i<=tot or j<=m;){
    		if(j>m or (i<=tot and p[i].y<=q[j].y)){
    			bit::insert(p[i].x,p[i].v);
    			++i;
    		}
    		else{
    			ans[q[j].v]=min(ans[q[j].v],bit::query(q[j].x));
    			++j;
    		}
    	}
    }
    int main(){
    	int n=read<int>();
    	for(int i=1;i<=n;++i) read(a[i]);
    	int m=read<int>();
    	for(int i=1;i<=m;++i) read(q[i].x),read(q[i].y),q[i].v=i;
    	fill(ans+1,ans+m+1,inf);
    	solve(n,m);
    	for(int i=1;i<=n;++i) a[i]=1e9-a[i];
    	solve(n,m);
    	for(int i=1;i<=m;++i) printf("%d
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    关键词user附近有语法错误
    Java期末考试冲刺总结
    getElementsByName&getElementById
    window.location.herf传值问题
    三种提示框
    statement没有返回结果集问题
    ajax从jsp向servlet传值
    java.sql.SQLException: Access denied for user ''@'localhost' (using password: NO)报错问题解决
    Unregistering application product with eureka with status DOWN
    输出废弃
  • 原文地址:https://www.cnblogs.com/autoint/p/12520137.html
Copyright © 2020-2023  润新知