题解 混乱邪恶

传送门

先粘小马优质博
然后好像就没什么可写的了……
注意删调试信息,注意数组开够

  • 貌似对于要用 \([1, n]\) 中数凑出一些特定数值的构造题,有一个套路是先按顺序匹配,求出这个状态下的权值
    然后通过错位构造出与要求的值的差值以构造出答案

应用到这个题上就是先顺序排序,然后临相匹配
这样得到一个性质是其中每个组的贡献很好计算,且相对“稳定”
没错我又在水博客

Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define ll long long
#define ull unsigned long long
#define fir first
#define sec second
#define make make_pair
#define pb push_back
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
int a[N];

namespace force{
	void solve() {
		int lim=1<<n;
		for (int s=0; s<lim; ++s) {
			ll sum=0;
			for (int i=0; i<n; ++i)
				if (s&(1<<i)) sum+=a[i+1];
				else sum-=a[i+1];
			if (sum==0) {
				puts("NP-Hard solved");
				for (int i=0; i<n; ++i) printf("%d ", s&(1<<i)?1:-1);
				printf("\n");
				exit(0);
			}
		}
		puts("Chaotic evil");
		exit(0);
	}
}

namespace task1{
	bitset<500500> f[1010];
	short back[500500];
	short ans[N];
	void check() {
		ll tem=0, sum=0;
		for (int i=1; i<=n; ++i) {
			if (ans[i]==1) tem+=a[i];
			sum+=a[i];
		}
		assert(tem==sum/2);
	}
	void solve() {
		// cout<<double(sizeof(f)+sizeof(back)+sizeof(ans)+sizeof(a))/1024/1024<<endl;
		f[0][0]=1;
		ll lim=0, sum=0; int pos;
		for (int i=1; i<=n; ++i) sum+=a[i];
		if (sum&1) {puts("Chaotic evil"); exit(0);}
		for (pos=1; pos<=n; ++pos) {
			lim+=a[pos];
			for (int j=0; j<=lim; ++j) if (f[pos-1][j]) {
				f[pos][j]=1;
			}
			for (int j=lim; j>=a[pos]; --j) {
				if (!f[pos][j] && f[pos-1][j-a[pos]]) {
					f[pos][j]=1;
					back[j]=pos;
				}
			}
			if (f[pos][sum/2]) break;
			// cout<<"f: "<<pos<<' '; for (int j=1; j<=sum/2; ++j) cout<<f[pos][j]<<' '; cout<<endl;
		}
		if (pos>n) {puts("Chaotic evil"); exit(0);}
		puts("NP-Hard solved");
		int now=pos, v=sum/2;
		while (now) {
			ans[now]=1;
			v-=a[now];
			--now;
			if (!now) break;
			now=back[v];
		}
		for (int i=1; i<=n; ++i) if (!ans[i]) ans[i]=-1;
		for (int i=1; i<=n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
		check();
		exit(0);
	}
}

namespace task2{
	int ans[N];
	ll sum[N];
	void solve() {
		if (n%2==0) {
			puts("NP-Hard solved");
			for (int i=1; i<=n/2; ++i) ans[i]=ans[n-i+1]=i&1?1:-1;
			for (int i=1; i<=n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
			exit(0);
		}
		else if ((n/2)%2==0) puts("Chaotic evil");
		else {
			puts("NP-Hard solved");
			ll k=n/2, want=k*k+(k*3+1)/2;
			for (int i=1; i<=n; ++i) {
				sum[i]=sum[i-1]+i;
				if (*lower_bound(sum, sum+i+1, sum[i]-want)==sum[i]-want) {
					int pos=lower_bound(sum, sum+i+1, sum[i]-want)-sum;
					for (int j=pos+1; j<=i; ++j) ans[j]=1;
					goto jump;
				}
			}
			jump: ;
			for (int i=1; i<=n; ++i) if (!ans[i]) ans[i]=-1;
			for (int i=1; i<=n; ++i) printf("%d%c", ans[i], " \n"[i==n]);
			exit(0);
		}
	}
}

namespace task{
	int ans[N], bkp[N], tot; ll sum;
	vector<pair<int, int>> v[N];
	void solve() {
		tot=n;
		for (int i=1; i<=n; ++i) bkp[i]=a[i];
		if (n&1) a[++n]=0;
		sort(a+1, a+n+1);
		for (int i=2; i<=n; i+=2) v[a[i]-a[i-1]].pb(make(a[i], a[i-1])), ans[a[i]]=1, ans[a[i-1]]=-1, sum+=a[i]-a[i-1];
		int pos=N-1;
		// cout<<"sum: "<<sum<<endl;
		pair<int, int> tem;
		while (sum) {
			// if (clock()>500000) cout<<"sum: "<<sum<<' '<<pos<<' '<<v[pos].size()<<endl;
			while (!v[pos].size()) --pos, assert(pos>0);
			// if (clock()>500000) cout<<"after while: "<<pos<<' '<<v[pos].size()<<endl;
			while (v[pos].size() && 2*pos<=sum) {
				tem=v[pos].back();
				sum-=2*pos;
				// cout<<"pos: "<<pos<<' '<<tem.fir<<' '<<tem.sec<<endl;
				swap(ans[tem.fir], ans[tem.sec]);
				v[pos].pop_back();
			}
			--pos;
		}
		puts("NP-Hard solved");
		for (int i=1; i<=tot; ++i) printf("%d%c", ans[bkp[i]], " \n"[i==n]);
		exit(0);
	}
}

signed main()
{
	freopen("chaoticevil.in", "r", stdin);
	freopen("chaoticevil.out", "w", stdout);

	n=read(); m=read();
	for (int i=1; i<=n; ++i) a[i]=read();
	// if (m<=20) force::solve();
	// else if (n==m) task2::solve();
	// else task1::solve();
	task::solve();

	return 0;
}
posted @ 2021-11-05 20:21  Administrator-09  阅读(0)  评论(0编辑  收藏  举报