E - M‘s Solution atcoder M-SOLUTIONS Programming Contest 2020

https://atcoder.jp/contests/m-solutions2020/tasks/m_solutions2020_e

考虑一个点,要么被x覆盖,要么被y覆盖,要么没被覆盖,所以我们只需要枚举每个点的3个状态就行了。

因为要覆盖一个点只需要一条铁路,至于新增的那条怎么影响其他点不用管,因为其他点的情况也被枚举了,所以其实一个点是被横的覆盖,他也有可能被其他点的竖的覆盖了,但对求答案无所谓

比赛的时候再判断函数里面排序加滑动窗口求答案3^n*nlogn TLE了,赛后加了个2^n*nlogn的预处理,直接处理出x选择情况时候对x的答案和y选择情况时对y的答案,然后再判断函数里面就只要扫一遍n了

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;

const int maxl=3e5+10;
const ll inf=1ll<<60;

int n,m,cas,k,cnt,totx,toty;
int st[maxl],numx[maxl],numy[maxl];
int xdis[1<<15][16],ydis[1<<15][16];
int xlen[1<<15],ylen[1<<15];
ll c[maxl],ans[maxl];
struct node
{
	int x,y,val,id;
}a[maxl],bx[maxl],by[maxl];
vector<int> tmpx,tmpy;
char s[maxl];
bool inx[maxl],iny[maxl]; 


inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{	
		scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].val);
		a[i].id=i;
		bx[i]=node{a[i].x,a[i].y,a[i].val,i};
		by[i]=node{a[i].x,a[i].y,a[i].val,i};
	}
	for(int i=0;i<=n;i++)
		ans[i]=inf;
} 

inline bool cmpx(const node &a,const node &b)
{
	return a.x<b.x;
}

inline bool cmpy(const node &a,const node &b)
{
	return a.y<b.y;
}

inline ll dis(int x,int y)
{
	return abs(x-y);
}

inline void jug(int sx,int sy)
{
	ll tmp=0;int len=xlen[sx]+ylen[sy];
	for(int i=1;i<=n;i++)
		tmp+=1ll*min(xdis[sx][i],ydis[sy][i])*a[i].val;
	ans[len]=min(ans[len],tmp);
}

inline void dfs(int k,int sx,int sy)
{
	if(k>n)
		jug(sx,sy);
	else
	{
		dfs(k+1,sx,sy);
		dfs(k+1,sx|(1<<(k-1)),sy);
		dfs(k+1,sx,sy|(1<<(k-1)));
	}
}

inline void mainwork()
{
	sort(bx+1,bx+1+n,cmpx);
	sort(by+1,by+1+n,cmpy);
	int up=1<<n;
	for(int s=0;s<up;s++)
	{
		tmpx.clear();tmpx.push_back(0);
		tmpy.clear();tmpy.push_back(0);
		for(int i=1;i<=n;i++)
		if((s>>(i-1))&1)
		{
			tmpx.push_back(a[i].x);
			tmpy.push_back(a[i].y);
		}
		sort(tmpx.begin(),tmpx.end());
		sort(tmpy.begin(),tmpy.end());
		tmpx.erase(unique(tmpx.begin(),tmpx.end()),tmpx.end());
		tmpy.erase(unique(tmpy.begin(),tmpy.end()),tmpy.end());
		int id=0;xlen[s]=tmpx.size();
		for(int i=1;i<=n;i++)
		{
			while(id+1<xlen[s] && dis(bx[i].x,tmpx[id+1])<dis(bx[i].x,tmpx[id]))
				++id;
			xdis[s][bx[i].id]=dis(bx[i].x,tmpx[id]);
		}
		id=0;ylen[s]=tmpy.size();
		for(int i=1;i<=n;i++)
		{
			while(id+1<ylen[s] && dis(by[i].y,tmpy[id+1])<dis(by[i].y,tmpy[id]))
				++id;
			ydis[s][by[i].id]=dis(by[i].y,tmpy[id]);
		}
		--xlen[s];--ylen[s];
	}
	dfs(1,0,0);
	for(int i=n;i>=0;i--)
	{	
		if(ans[i]!=inf)
			break;
		ans[i]=0;
	}
}

inline void print()
{
	for(int i=0;i<=n;i++)
		printf("%lld\n",ans[i]);
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/107587296
今日推荐