zoukankan      html  css  js  c++  java
  • 题解-bzoj4320 Homework

    Problem

    bzoj4320

    Solution

    前置技能:分块+线段树+卡常+一点小小的数学知识

    考试时A的

    这种题无论怎么处理总有瓶颈,套路分块,设(k)以下的插入时直接暴力预处理,查询时直接调用;(k)以上的插入时不管,查询时线段树查找每个模意义下的区间

    核心代码:

    if(opt[0]=='A'){
    	for(rg int i=1;i<=k;++i)f[i]=min(f[i],x%i);
    	update(1,n,1,x);
    }
    else
    	if(x<=k)printf("%d
    ",f[x]);
    	else {
    		int res(inf);
    		for(rg int i=0;i<=n;i+=x)
    			res=min(res,query(1,n,1,max(1,i),min(i+x-1,n))-i);
    		printf("%d
    ",res);
    	}
    

    考虑到当分界线为(k),变量为(x)时,插入复杂度为(O(k)),查询时复杂度为(O(1))(O(frac nxlog_2n)leq O(frac nklog_2n))

    如果直接采用大众分块做法(块大小为(sqrt n)),则算法瓶颈为(O(sqrt n log_2n)),总体复杂度(O(nsqrt nlog_2n))无法通过此题

    考虑算法瓶颈,总体单次复杂度为(O(k+frac nklog_2n)),利用基本不等式(a+bgeq 2sqrt{ab}),得知总体单次复杂度最小为(O(2sqrt{kcdot frac nk log_2n})=O(sqrt{nlog_2n})),而满足这个不等式取等的条件是(a=bLeftrightarrow k=frac nk log_2nLeftrightarrow k=sqrt {nlog_2n}),再考虑上取膜运算和线段树的常数因子影响,取(k=1732)时最优

    注意,以上并非平均情况下的最优,而是最差情况下的最优(一般情况下(k=sqrt n)的程序甚至更快),也就是说,如果出题人看了你的程序,精心构造数据卡你,(k=1732)的程序被卡后是最快的,可以保证复杂度在(O(nsqrt {n log_2 n}))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define rg register
    
    template <typename _Tp> inline _Tp read(_Tp&x){
    	char c11=getchar(),ob=0;x=0;
    	while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    	while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
    }
    
    const int N=301000,inf=0x7fffffff;
    int f[N],s[N<<2],fc[N];
    int Q,k,n=300000;
    
    void pre(){// 1817|1732
    	k=1732;
    	for(rg int i=1;i<=k;++i)f[i]=inf;
    /*	fc[0]=-1;
    	for(rg int i=1;i<=n;++i)fc[i]=fc[i>>1]+1;
    	double mi=inf,tp;k=1;
    	for(rg int i=2;i<=n;++i)
    		if((tp=abs(i*i-1.0*n*fc[i]))<1.0*mi)mi=tp,k=i;*/
    }
    
    void build(int l,int r,int x){
    	s[x]=inf;
    	if(l==r)return ;
    	int mid(l+r>>1);
    	build(l,mid,x<<1);
    	build(mid+1,r,x<<1|1);
    	return ;
    }
    
    inline void update(int l,int r,int x,int ps){
    	if(l==r){s[x]=l;return ;}
    	int mid(l+r>>1);
    	if(ps<=mid)update(l,mid,x<<1,ps);
    	else update(mid+1,r,x<<1|1,ps);
    	s[x]=min(s[x<<1],s[x<<1|1]);return ;
    }
    
    inline int query(int l,int r,int x,int L,int R){
    	if(L<=l&&r<=R)return s[x];
    	int mid(l+r>>1),res(inf);
    	if(L<=mid)res=min(res,query(l,mid,x<<1,L,R));
    	if(mid<R)res=min(res,query(mid+1,r,x<<1|1,L,R));
    	return res;
    }
    
    int main(){
    	freopen("f.in","r",stdin);
    	freopen("f.out","w",stdout);
    	pre();read(Q);
    	build(1,n,1);
    	char opt[2];int x;
    	while(Q--){
    		scanf("%s",opt);read(x);
    		if(opt[0]=='A'){
    			for(rg int i=1;i<=k;++i)f[i]=min(f[i],x%i);
    			update(1,n,1,x);
    		}
    		else
    			if(x<=k)printf("%d
    ",f[x]);
    			else {
    				int res(inf);
    				for(rg int i=0;i<=n;i+=x)
    					res=min(res,query(1,n,1,max(1,i),min(i+x-1,n))-i);
    				printf("%d
    ",res);
    			}
    	}return 0;
    }
    
  • 相关阅读:
    JavaScript中对事件简单的理解
    正则表达式 RE模块
    模块
    面向对象进阶
    元类详细解释
    四.面向对象和函数补充
    四.函数
    Python的基础知识:
    五层协议及tcp三次握手四次挥手
    nginx常见错误
  • 原文地址:https://www.cnblogs.com/penth/p/9310928.html
Copyright © 2011-2022 走看看