• 【UER #7】天路


    居然还有基于近似化答案的做法的题
    /xia

    先说一下自己会做的 \(70\) 分做法。

    考虑 \(f_i\) 答案显然递增。

    实际上求的即是 \(f_k = \min_L(\min_{a_L,..a_{L + k - 1}} - \max_{a_L,..a_{L + k - 1}} \ \ \ )\)

    不如反过来考虑,令 \(g_k\) 为区间最大值和最小值差值为 \(k\) 的最大区间长度。

    那么 \(f_i\)\(\min_{k > i}g_k\)

    因为在随机数据下笛卡尔树树高 \(log\) ,那么直接对最小值建笛卡尔树,然后确定最小值,枚举最大值确定区间范围即可。

    我写的是 \(O(nlog^2)\) 的,实际上预处理可以做到 \(O(nlog)\)

    点击查看代码
    //晦暗的宇宙,我们找不到光,看不见尽头,但我们永远都不会被黑色打倒。——Quinn葵因
    #include<bits/stdc++.h>
    #define ll long long
    #define N 100005
    
    int n;
    
    int a[N];
    
    int st[N],top;
    
    int ls[N],rs[N];
    
    inline void ins(int x){
    	int las = 0;
    	while(top && a[st[top]] > a[x])las = st[top],-- top;
    	if(top)rs[st[top]] = x;if(las)ls[x] = las;
    	st[++top] = x;
    }
    
    int lg[N],S[N][20];
    
    inline int MAX(int x,int y){int len = y - x + 1;return std::max(S[x][lg[len]],S[y - (1ll << lg[len]) + 1][lg[len]]);}
    
    int root;
    
    int L[N],R[N];
    
    #define mid ((l + r) >> 1)
    
    int TS[N * 10];
    
    inline void dfs(int x){
    	L[x] = x,R[x] = x;
    	if(ls[x])dfs(ls[x]),L[x] = L[ls[x]];
    	if(rs[x])dfs(rs[x]),R[x] = R[rs[x]];
    //	std::cout<<"DEL "<<x<<" "<<L[x]<<" "<<R[x]<<"\n";	
    	for(int i = L[x];i < x;++i){
    		int l = i,r = R[x],Ri = i,Li;while(l <= r){if(MAX(i,mid) == a[i])Ri = mid,l = mid + 1;else r = mid - 1;}
    		if(Ri < x)continue; 
    		l = L[x],r = i,Li = i;while(l <= r){if(MAX(mid,i) == a[i])Li = mid,r = mid - 1;else l = mid + 1;}
    //		std::cout<<"("<<a[i]<<" "<<a[x]<<")"<<" "<<Li<<" "<<Ri<<"\n";
    		int len = Ri - Li + 1;TS[a[i] - a[x]] = std::max(len,TS[a[i] - a[x]]);
     	}
     	for(int i = R[x];i > x;--i){		 	
    		int l = L[x],r = i,Li = i,Ri;while(l <= r){if(MAX(mid,i) == a[i])Li = mid,r = mid - 1;else l = mid + 1;}
    //		std::cout<<"RIGHT "<<i<<" "<<Li<<" "<<Ri<<"\n";			
    		if(Li > x)continue; 
    		l = i,r = R[x],Ri = i;while(l <= r){if(MAX(i,mid) == a[i])Ri = mid,l = mid + 1;else r = mid - 1;}
    //		std::cout<<"("<<a[i]<<" "<<a[x]<<")"<<" "<<Li<<" "<<Ri<<"\n";
    		int len = Ri - Li + 1;TS[a[i] - a[x]] = std::max(len,TS[a[i] - a[x]]);	 
    	}
    } 
    
    int fans[N];
    
    int main(){
    //	freopen("t.in","r",stdin);
    //	freopen("t.out","w",stdout);
    	scanf("%d",&n);
    	for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
    	for(int i = 1;i <= n;++i)ins(i);
    	for(int i = 1;i <= n;++i)S[i][0] = a[i];
    	lg[0] = -1;for(int i = 1;i <= n;++i)lg[i] = lg[i >> 1] + 1;
    	for(int j = 1;j <= 20;++j)for(int i = 1;i + (1ll << j) - 1 <= n;++i)
    	S[i][j] = std::max(S[i][j - 1],S[i + (1ll << (j - 1))][j - 1]);
    	root = st[1];dfs(root);
    	for(int i = 1;i <= n + 1;++i)fans[i] = 1e6; 
    	for(int i = 1;i <= 1e6;++i)fans[TS[i]] = std::min(fans[TS[i]],i);
    	for(int i = n;i >= 2;--i)fans[i] = std::min(fans[i + 1],fans[i]);
    	for(int i = 2;i <= n;++i)std::cout<<fans[i]<<"\n";
    }
     
    

    接下来考虑正解。

    每次找到 \(\leq las * 1.05\) 的边界点,并把区间赋值为该答案。

    点击查看代码
    #include<cstdio>
    #include<algorithm>
    #define N 100010
    
    using namespace std;
    
    int l1,l2,r1,r2,ans,n;
    int a[N],q1[N],q2[N];
    
    int work(int x)
    {
    	l1=l2=1; r1=r2=ans=0;
    	for(int i=1,now=1;i<=n;i++)
    	{
    		while(r1>=l1&&a[q1[r1]]<a[i])r1--;
    		while(r2>=l2&&a[q2[r2]]>a[i])r2--;
    		q1[++r1]=i; q2[++r2]=i;
    		while(a[q1[l1]]-a[q2[l2]]>x)
    		{
    			if(q1[l1]==now)l1++;
    			if(q2[l2]==now)l2++;
    			now++;
    		}
    		ans=max(ans,i-now+1);
    	}
    	return ans;
    } 
    
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",a+i);
    	for(int now=0,l=2,r;l<=n;now=max(now+1,(int)(now*1.05)))
    	{
    		r=work(now);
    		for(;l<=r;l++)printf("%d\n",now);
    	}
    	return 0;
    }
    

    \(O(log1.05)\) 也是 \(log\) 阿(恼

  • 相关阅读:
    An AODV Tutorial
    MFC去掉单文档的"无标题-"的方法
    win32 openss 编译
    ASP.NET实现RENREN SIG计算
    std::string str.c_str() const
    fopen
    curl with ssl support for win32
    VC++ utf8 Unicode GB2312 编码转换
    编码转换
    VirtualBox uuid冲突问题
  • 原文地址:https://www.cnblogs.com/dixiao/p/16178210.html
Copyright © 2020-2023  润新知