题解 混乱邪恶
先粘小马优质博
然后好像就没什么可写的了……
注意删调试信息,注意数组开够
- 貌似对于要用 \([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;
}