挂个和标案差±1的折半+双指针
查看原帖
挂个和标案差±1的折半+双指针
186045
itisover楼主2022/3/5 18:23

大概就是让左边的x和y升序,右边的降序

#include<bits/stdc++.h>
#define int long long
#define ll long long
#define pb push_back
#define pii pair<ll,ll>
#define mp make_pair
#define fi first
#define se second
using namespace std;
template <class T> inline T read(){
	T r=0,f=0;char c=getchar();
	while(!isdigit(c)) f|=c=='-',c=getchar();
	while(isdigit(c)) r=(r<<3)+(r<<1)+(c^48),c=getchar();
	return f?-r:r;
}
const int _=45;
int n,xg,yg,way[_][2];
struct WATS2{ll x,y,cnt;};
map<pii,ll> p1[_],p2[_];
vector<WATS2> up1[_],up2[_];
bool cmp1(WATS2 x,WATS2 y){return x.x==y.x?x.y<y.y:x.x<y.x;}
bool cmp2(WATS2 x,WATS2 y){return x.x==y.x?x.y>y.y:x.x>y.x;}
void dfs(int x,int ed,int cnt,ll dx,ll dy,map<pii,ll> *S){
	if(x>ed){++S[cnt][mp(dx,dy)];return;}
	dfs(x+1,ed,cnt,dx,dy,S);
	dfs(x+1,ed,cnt+1,dx+way[x][0],dy+way[x][1],S);
}
signed main(){
	n=read<int>(),xg=read<int>(),yg=read<int>();
	for(int i=1;i<=n;++i) way[i][0]=read<int>(),way[i][1]=read<int>();
	dfs(1,n/2,0,0,0,p1),dfs(n/2+1,n,0,0,0,p2);
	for(int i=0;i<=n;++i){
		for(auto x:p1[i]) up1[i].pb({x.fi.fi,x.fi.se,x.se});
		for(auto x:p2[i]) up2[i].pb({x.fi.fi,x.fi.se,x.se});
		sort(up1[i].begin(),up1[i].end(),cmp1),sort(up2[i].begin(),up2[i].end(),cmp2);
	}
	for(int k=1;k<=n;++k){
		ll ans=0;
		for(int a=0;a<=k;++a){
			int j=0;
			for(auto x:up1[a]){
				while(j<up2[k-a].size()&&up2[k-a][j].x+x.x>xg) ++j;
				if(j==up2[k-a].size()||up2[k-a][j].x+x.x!=xg) continue;
				while(j<up2[k-a].size()&&up2[k-a][j].y+x.y>yg) ++j;
				if(j==up2[k-a].size()||up2[k-a][j].y+x.y!=yg) continue;
				ans+=x.cnt*up2[k-a][j].cnt; ++j;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}
2022/3/5 18:23
加载中...