这是一个很邪门的贪心
考虑到最终答案是每个正方形的贡献除以总的正方形个数,而正方形个数容易计算,那么只需最大化贡献。
从题面给出的图易得 每个点被覆盖的次数是一定的,我们只需要在被覆盖最多的点上面放置小鱼即可让答案最大化

接着容易想到一个暴力的做法,就是 \(n^2\) 统计每个点的贡献,取前 \(k\) 个点放置小鱼。
再考虑优化,每个点被覆盖情况实际上可以看成长和宽的被覆盖情况的乘积,我们把正方形看成是两条线段,分别覆盖在长和宽上,这样的两条线段对应原矩形中唯一一个正方形。设长和宽被覆盖次数为两个序列 \(a_i\) \(b_j\) ,原矩形为 \(c_{i,j}\) ,那么 \(c_{i,j}=a_i * b_j\) , 我们的任务就是计算出前 \(k\) 大的 \(c_{i,j}\) ,考虑把 \(a_i\) \(b_j\) 排序,从大到小分别枚举 \(i\)\(j\) 把对应的乘积放入平衡树或者 \(set\) 。考虑到我们是从大到小枚举,如果一个乘积 \(a_i * b_j\) 在平衡树中的排位大于 \(k\) ,继续下去的话乘积只会更小,那么他自己和他后面的元素也就都没有价值了,我们直接 \(break\) 掉,这个做法时间复杂度目测不会超过 \(n \sqrt{n} log{n}\) ,实际测试跑的快得多。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
typedef long long ll;
using namespace std;
ll n,m,k,r,a[400001],b[400001],ans;

struct Splay{
	#define N (ll)3e6
	ll siz[N],fa[N],son[N][2],vul[N],tot,root,cnt[N];
	void UP(ll x){
		siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
	}
	bool dir(ll x){
		return son[fa[x]][1]==x;
	}
	void rotate(ll x){
		ll y=fa[x],z=fa[y],k=dir(x),w=son[x][k^1];
		fa[x]=z,son[z][dir(y)]=x;
		fa[y]=x,son[x][k^1]=y;
		fa[w]=y,son[y][k]=w;
		UP(y),UP(x); 
	}
	void splay(ll x,ll goal=0){
		while(fa[x]!=goal){
			ll y=fa[x],z=fa[y];
			if(z!=goal){
				if(dir(x)==dir(y))rotate(y);
				else rotate(x);
			}
			rotate(x);
		}
		if(!goal)root=x;
	}
	void find(ll x){
		if(!root)return ;
		ll cur=root;
		while(son[cur][x>vul[cur]]&&x!=vul[cur])
			cur=son[cur][x>vul[cur]];
		splay(cur);
	}
	ll LR(ll x,ll k){
		find(x);
		if(vul[root]<x&&k==0)return root;
		if(vul[root]>x&&k==1)return root;
		ll cur=son[root][k];
		while(son[cur][k^1])cur=son[cur][k^1];
		return cur;
	}
	ll insert(ll x){
		ll cur=root,p=0;
		while(cur&&x!=vul[cur]){
			p=cur;
			cur=son[cur][x>vul[cur]];
		}
		if(cur)cnt[cur]++;
		else {
			cur=++tot;
			if(p)son[p][x>vul[p]]=cur;
			siz[cur]=cnt[cur]=1;
			fa[cur]=p,vul[cur]=x;
			son[cur][0]=son[cur][1]=0;
		}
		splay(cur);
	}
	void Delete(ll x){
		ll le=LR(x,0),re=LR(x,1);
		splay(le),splay(re,le);
		ll del=son[re][0];
		if(cnt[del]>1)cnt[del]--,splay(del);
		else son[re][0]=0;
		UP(re),UP(le);
	}
	ll get_rank(ll x){
		find(x);
		if(vul[root]>=x)return siz[son[root][1]]+cnt[root];
		return siz[son[root][1]];
	}
}T;

int main(){
	T.insert(-1e15);
	T.insert(1e15);
	cin>>n>>m>>r>>k;
	for(ll i=1;i<=n-r+1;i++)a[i]++,a[i+r]--;
	for(ll i=1;i<=m-r+1;i++)b[i]++,b[i+r]--;
	for(ll i=1;i<=n;i++)a[i]+=a[i-1];
	for(ll i=1;i<=m;i++)b[i]+=b[i-1];
	sort(1+a,1+a+n);
	sort(1+b,1+b+m);
	for(ll i=n;i>=1;i--){
		for(ll j=m;j>=1;j--){
			ll sum=a[i]*b[j];
			if(T.get_rank(sum)>k+1)break;
			T.insert(sum);
		}
	}
	while(k--){
		ll cur=T.LR(1e12,0);
		ans+=T.vul[cur];
		T.Delete(T.vul[cur]);
	}
	long double Ans=1.0*ans/(n-r+1)/(m-r+1);
	printf("%.10Lf",Ans);
}

原文地址:http://www.cnblogs.com/caijiLYC/p/16855976.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性