联合省选Day2 T1求调
  • 板块学术版
  • 楼主XZhuRen
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/3/4 03:06
  • 上次更新2024/3/4 16:06:18
查看原帖
联合省选Day2 T1求调
715971
XZhuRen楼主2024/3/4 03:06

大样例没问题,云斗只有20pts

#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define ll1 long long
#define int long long
const int N=3e5;
ll1 k;
int m,n,n1;
int a[N];
ll1 w[N];
void init(){
	scanf("%lld%lld",&m,&k);
	n=(1<<(m+1))-1;
	n1=(1<<(m))-1;
	for(int i=1;i<=n1;i++)
		scanf("%lld",&w[i]);
	for(int i=n1+1;i<=n;i++)
		scanf("%lld",&a[i]);
}
struct node{
	int dataa;
	ll1 cost;
	bool lr,isc;
	ll1 lc,rc;//分给左边,右边的权值和。优先访问边有优先级 
};
vector<node>my[N];
node tmp1[N],tmp2[N],tmp;
node mm[N];
int sum1,sum2;
#define ls root<<1
#define rs (root<<1)+1
void dfs(int root){//树上dp,处理出vector[i][j]。 
	if((ls)>n){
		my[root].push_back((node){a[root],0,0,0});
		return;
	}
	dfs(ls);dfs(rs);
	int x,y;
	sum1=sum2=0;
	x=my[ls].size();
	y=my[rs].size();
	mm[y-1]=my[rs][y-1];
	for(int i=y-2;i>=0;i--){
		mm[i]=my[rs][i];
		if(mm[i+1].cost<=mm[i].cost)mm[i]=mm[i+1];
	}
	for(int i=0;i<x;i++){
		tmp=my[ls][i];
		tmp.isc=0;
		tmp.lr=0;
		if(mm[y-1].dataa>tmp.dataa){
			int l=0,r=y-1,mid;
			while(l<r){
				mid=(l+r)/2;
				if(my[rs][mid].dataa>tmp.dataa)r=mid;
				else l=mid+1;
			}
			tmp.cost+=mm[l].cost;
			tmp.lc=tmp.cost-mm[l].cost;//
			tmp.rc=mm[l].cost;//
			if(w[root]<mm[l].cost){
				tmp.cost=tmp.cost-mm[l].cost+w[root],tmp.isc=1;
				tmp.rc=0;//
			}
		}else tmp.cost=tmp.cost+w[root],tmp.isc=1;
		if(tmp.cost<=k)tmp1[++sum1]=tmp;
	}
	
	mm[x-1]=my[ls][x-1];
	for(int i=x-2;i>=0;i--){
		mm[i]=my[ls][i];
		if(mm[i+1].cost<=mm[i].cost)mm[i]=mm[i+1];
	}
	for(int i=0;i<y;i++){
		tmp=my[rs][i];
		tmp.isc=0;
		tmp.lr=1;
		if(mm[x-1].dataa>tmp.dataa){
			int l=0,r=x-1,mid;
			while(l<r){
				mid=(l+r)/2;
				if(my[ls][mid].dataa>tmp.dataa)r=mid;
				else l=mid+1;
			}
			if(tmp.cost+mm[l].cost<=k){
				tmp.cost=tmp.cost+mm[l].cost;
				tmp.rc=tmp.cost-mm[l].cost;//
				tmp.lc=mm[l].cost;//
				tmp2[++sum2]=tmp;
			}
		}
	}
	
	tmp1[sum1+1]=tmp2[sum2+1]=(node){1145141919,1145141919,0,0};
	for(int i=1,j=1;i<=sum1||j<=sum2;){//归并保持单调性 
		if(tmp1[i].dataa<tmp2[j].dataa)
			my[root].push_back(tmp1[i]),i++;
		else my[root].push_back(tmp2[j]),j++;
	}
}
ll1 dfs1(int root,int now,ll1 K){//走 
	if(ls>n){
		printf("%lld ",a[root]);
		return K;//剩余的权 
	}
	bool LorR=0;int lenth=my[root].size();
	bool iscc=0;
	int Lc,Rc;
	for(int i=0;i<lenth;i++){
		if(my[root][i].dataa==now){
			LorR=my[root][i].lr;
			Lc=my[root][i].lc,Rc=my[root][i].rc;
			if(my[root][i].isc==1)
				iscc=1;
		}
	}
	if(iscc==1)K-=w[root];//被使用的
	ll1 tK=K; 
	K=(LorR==0?Rc:Lc);
	ll1 K1;
	K1=tK-K;
	int too=0;
	K=K+dfs1((ls)+LorR,now,K1);//继续目标,卓玛赵常升起 
	int x=my[ls].size();
	int y=my[rs].size();
	if(LorR==1){//查找左边数 
		for(int i=0;i<x;i++){
			if(my[ls][i].dataa<now)continue;
			if(my[ls][i].cost<=K)too=my[ls][i].dataa;
		}
		return dfs1(ls,too,K);
	}else{//查找右边/替换 
		if(iscc==1){
			for(int i=0;i<y;i++){
				if(my[rs][i].cost<=K)too=my[rs][i].dataa;
			}
			if(too>now)K+=w[root];
			return dfs1(rs,too,K);	
		}else{
			for(int i=0;i<y;i++){
				if(my[rs][i].dataa<now)continue;
				if(my[rs][i].cost<=K)too=my[rs][i].dataa;
			}
			return dfs1(rs,too,K);	
		}
	}
}
void work(){
	for(int i=0;i<=n;i++)my[i].clear();
	dfs(1);
	int x=my[1][my[1].size()-1].dataa;
	dfs1(1,x,k);
}
signed main(){
//	freopen("maze.in","r",stdin);
//	freopen("maze.out","w",stdout);
	int T;
	scanf("%lld",&T);
	while(T--){
		init();
		work();
		printf("\n");
	}
	return 0;
}
2024/3/4 03:06
加载中...