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;
}