贪心56pts求hack
查看原帖
贪心56pts求hack
261300
GoldenLeaf楼主2023/10/18 16:28

思路:把正负分开做,以正数为例,按c[i]从大到小做,设其编号为x,若前x-1个位置没填满就填并造成贡献,否则能填在第x个位置就填并不贡献,否则随便扔到后面,造成负贡献。负的部分就是正的反过来。 树状数组就是维护前x个位置填了几个数的。

大样例过了,但56pts,第一个测试点就WA了。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<ll,int> pii;

const int N=2e5+5;

pii c[N];
ll C[N];

bool cmp(pii x,pii y){
	if(x.first!=y.first)return x.first>y.first;
	else return x.second>y.second;
}

int t[N],n;

int lowbit(int x){
	return x&-x;
}

void add(int x,int v){
	for(int i=x;i<=n;i+=lowbit(i))t[i]+=v;
}

int query(int x){
	int ans=0;
	for(int i=x;i;i-=lowbit(i))ans+=t[i];
	return ans;
}

void solve(){
	memset(t,0,sizeof(t));
	int cnt;
	scanf("%d",&n);
	for(int i=1,_;i<=n;i++)
		scanf("%d",&_);
	for(int i=1;i<=n;i++)
		scanf("%lld",&C[i]);
	ll ans=0;
	cnt=0;
	for(int i=1,j=1;i<=n;i++)
		if(C[i]>0ll){
			c[j]={C[i],i};
			j++;
			cnt++;
		}
	sort(c+1,c+1+cnt,cmp);
	memset(t,0,sizeof(t));
	for(int i=1;i<=cnt;i++){
		ll w=c[i].first;
		int x=c[i].second;
		if(x>cnt)ans+=w;
		else{
			if(query(x-1)<x-1){
				add(x-1,1);
				ans+=w;
			}
			else if(query(x)<x)
				add(x,1);
			else ans-=w;				
		}
	}
	cnt=0;
	for(int i=1,j=1;i<=n;i++)
		if(C[i]<0ll){
			c[j]={-C[i],n+1-i};
			j++;
			cnt++;
		}
	sort(c+1,c+1+cnt,cmp);
	memset(t,0,sizeof(t));
	for(int i=1;i<=cnt;i++){
		ll w=c[i].first;
		int x=c[i].second;
		if(x>cnt)ans+=w;
		else{		
			if(query(x-1)<x-1){
				add(x-1,1);
				ans+=w;
			}
			else if(query(x)<x)
				add(x,1);
			else ans-=w;				
		}
	}
	printf("%lld\n",ans);
}

int main(){
//	freopen("contrib.in","r",stdin);
	int T;
	scanf("%d",&T);
	while(T--)solve();
	return 0;
}
2023/10/18 16:28
加载中...