【bzoj4071】[Apio2015]巴邻旁之桥 三分套三分

三分一下第一座桥,三分一下第二座桥,貌似就解决了。

UOJ跑的死慢,bz也T掉了。


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 100010 
#define inf 1000000000000000

using namespace std;

struct yts
{
	int op1,x1,op2,x2;
}a[maxn];

int n,m,k,mx;
long long ans;
char s[10];

long long calc(int x,int y)
{
	long long ans=0;
	for (int i=1;i<=n;i++)
	  if (a[i].op1==a[i].op2) ans+=abs(a[i].x2-a[i].x1);
	  else ans+=min(abs(a[i].x2-x)+abs(a[i].x1-x),abs(a[i].x2-y)+abs(a[i].x1-y))+1;
	return ans;
}

long long solve(int x)
{
	long long ans=0;
	if (k==1)
	{
		for (int i=1;i<=n;i++)
		  if (a[i].op1==a[i].op2) ans+=abs(a[i].x2-a[i].x1);
		  else ans+=abs(a[i].x2-x)+abs(a[i].x1-x)+1;
	}
	else
	{
		int l=0,r=mx;
		while (r-l>=3)
		{
			int mid=l+(r-l)/3,midmid=r-(r-l)/3;
			if (calc(x,mid)<=calc(x,midmid)) r=midmid; else l=mid;
		}
		ans=inf;
		for (int i=l;i<=r;i++) ans=min(ans,calc(x,i));
	}
	return ans;
}

int main()
{
	scanf("%d%d",&k,&n);
	for (int i=1;i<=n;i++)
	{
		scanf("%s%d",s,&a[i].x1);
		if (s[0]=='A') a[i].op1=0; else a[i].op1=1;
		scanf("%s%d",s,&a[i].x2);
		if (s[0]=='A') a[i].op2=0; else a[i].op2=1;
		mx=max(mx,max(a[i].x1,a[i].x2));
	}
	int l=0,r=mx;
	while (r-l>=3)
	{
		int mid=l+(r-l)/3,midmid=r-(r-l)/3;
		if (solve(mid)<=solve(midmid)) r=midmid; else l=mid;
	}
	ans=inf;
	for (int i=l;i<=r;i++) ans=min(ans,solve(i));
	printf("%lld\n",ans);
	return 0;
}


你可能感兴趣的:(【bzoj4071】[Apio2015]巴邻旁之桥 三分套三分)