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
#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 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.xn)
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<>(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=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;
}