zoukankan      html  css  js  c++  java
  • [USACO16JAN]愤怒的奶牛Angry Cows (单调队列优化dp)

    题目链接

    Solution

    应该可以用二分拿部分分,时间 (O(n^2logn))
    然后可以考虑 (n^2) (dp) ,令 (f_i) 代表 (i) 点被激活,然后激活 (i) 之前所有点所需的半径。
    那么很显然 (f[i]=min(max(pos[i]-pos[j],f[j]))) 其中 (j<i)
    再从后往前记录一个 (g[i]) , 那么答案就为 (min(max(f[i],g[i])))以及还要考虑两点中间的,其中 (1<=i<=n)
    但是如果 (n^2) 处理解决不了 (50000) 的数据。
    考虑优化。
    观察到 (f[j]) 是递增的,而 (pos[i]-pos[j]) 是递减的。
    那么只要是后面的 (f[i]) 比前面小的话,那么肯定他是最优解。
    所以维护一个 (f[i]) 递增的单调队列即可。

    Code

    #include<bits/stdc++.h>
    #define ll long long
    #define N 50005
    using namespace std;
    
    ll n,a[N];
    
    double pos[N],f[N],g[N];
    void in(ll &x)
    {
    	ll f=1,w=0;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
    	x=f*w; return;
    }
    
    int main()
    {
    	in(n);
    	for(int i=1;i<=n;i++)
    	{
    		ll x; in(x);
    		pos[i]=x*1.0;
    	}
    	sort(pos+1,pos+n+1);
    	if(n==1){cout<<0<<endl;return 0;}
    	if(n==2){cout<<pos[2]-pos[1]<<endl;return 0;}
    	f[2]=pos[2]-pos[1];
    	int head=1,tail=0;
    	a[++tail]=2;
    	for(int i=3;i<=n;i++)
    	{
    		while(max(pos[i]-pos[a[head]],f[a[head]]+1.0)>max(pos[i]-pos[a[head+1]],f[a[head+1]]+1.0))
    		{if(head==tail)break;head++;}
    		f[i]=max(pos[i]-pos[a[head]],f[a[head]]+1.0);
    		while(f[i]<f[a[tail]]){tail--;if(tail<head)break;}
    		a[++tail]=i;
    	}
    	g[n-1]=pos[n]-pos[n-1];
    	memset(a,0,sizeof(a));
    	head=tail=1;
    	a[tail]=n-1;
    	double ans=(0x3f3f3f3f3f)*1.0;
    	for(int i=n-2;i>=1;i--)
    	{
    		while(max(pos[a[head]]-pos[i],g[a[head]]+1)>max(pos[a[head+1]]-pos[i],g[a[head+1]]+1))
    		{if(head==tail)break;head++;}
    		g[i]=max(pos[a[head]]-pos[i],g[a[head]]+1);
    		while(g[i]<g[a[tail]]){tail--;if(tail<head)break;}
    		a[++tail]=i;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		ans=min(max(f[i]*1.0,g[i]*1.0),ans);
    		if(i>1)
    		ans=min(max((pos[i]-pos[i-1])*1.0/2,max(f[i-1]*1.0+1,g[i]*1.0+1)),ans);
    	}
    	printf("%.1lf",ans);
    	return 0;
    }
    
  • 相关阅读:
    Bash的提示符
    小笨霖英语笔记本(5)
    什么是VLAN
    阅读笔记:双核心Opteron处理器
    小笨霖英语笔记本(4)
    搭乘CCNUMA快车
    得到tnsnames.ora文件的位置 zz
    关于64位Windows操作系统中的注册表 zz
    Temp.Misc
    HttpHandler HttpModule入门篇
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/11838565.html
Copyright © 2011-2022 走看看