preface
Construction problem? Or MO II trial modification? It's okay.
subject
Main idea of the title:
A group of new guests came to the tavern. In order to entertain them, Bob decided to arrange a wonderful battle!
Bob selected \ (n \) followers \ (a_i \) from \ (m \) followers. Adhering to the principle of simplicity, the combat effectiveness of these \ (m \) followers is an integer between \ ([1,m] \).
In order to make the battle more ornamental, there should not be too few followers participating in the battle, so \ (\ lfloor \ frac{2m}{3} \ rfloor < n \ Le m \).
Bob thinks the best battle is to match two equal opponents! But then he made a mistake, because there were more than two people here. He didn't know how to divide the team! So this task is entrusted to you who works nearby. You need to divide these \ (n \) followers into \ (2 \) groups, and the sum of combat effectiveness of each group is the same.
If there is no solution, it is necessary to report Chaotic evil. Otherwise, NP hard solved is output first, and then \ (- 1 \) and \ (1 \) represent grouping.
\(3\le n\le m \le 10^6. \) ensure that the sum of the combat effectiveness of Bob's entourage is even.
explain
Tell a joke, from big to small, violent, greedy dfs has 88pts.
Obviously, there is no idea about the construction problem, so let's talk about the construction method directly.
First, treat \ (n \) as an even number and add \ (0 \) if it is odd.
Then sort and make \ (d_i=a_{2i}-a_{2i-1} \), and you can find \ (\ sum d_i \ Le m - \ frac {n}{2} < n \), and \ (\ sum d_i \) is even.
Let's try to adjust the positive and negative of \ (d_i \) to achieve our goal. We make \ (N=\frac{n}{2} \), and the limit can be expressed as \ (\ sum d_i < 2n \).
Consider inductive construction:
- \(N=1 \), because \ (\ sum d_i < 2n \) and \ (\ sum d_i \) are even.
- \(n > 1 \), if \ (d_i=1 \), there is obviously a solution. Otherwise, we select the largest \ (D {Max} \) and the smallest \ (D {min} \), delete them and add \ (D {Max} - D {min} \). It is not difficult to find that \ (\ sum d_i \) at least reduces \ (2 \), \ (\ sum d_i \) is still even, \ (N'=N-1 \) and is successfully summarized into the sub problem.
The official solution ends here. How can it be realized?
Here are two ideas:
- We directly simulate this process and consider how to mark the symbol inversion. We can adopt the method of set + heuristic combination. The time complexity \ (O(n\log_2^2n) \) can be achieved if the merging heap is used \ (O(n\log_2n) \), which has not been tried, but the theory can.
- Despite my rubbish approach, let's look at Mr. Juan's approach. We directly look up the set of \ (2N \) points, \ (i \) and \ (i+N \) represent symbols. Each time we do it, we only need to connect the edges to represent the similarities and differences between the positive and negative signs of numbers. To find the maximum and minimum, we can use set. The time complexity \ (O(n\log_2n) \) and the constant are smaller, and the following code is the same approach.
code
Small constant
//12252024832524 #include <bits/stdc++.h> #define TT template<typename T> using namespace std; typedef long long LL; const int MAXN = 1000005; int n,m,sg; int a[MAXN],od[MAXN],f[MAXN]; bool ans[MAXN]; LL Read() { LL x = 0,f = 1; char c = getchar(); while(c > '9' || c < '0'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();} return x * f; } TT void Put1(T x) { if(x > 9) Put1(x/10); putchar(x%10^48); } TT void Put(T x,char c = -1) { if(x < 0) putchar('-'),x = -x; Put1(x); if(c >= 0) putchar(c); } TT T Max(T x,T y){return x > y ? x : y;} TT T Min(T x,T y){return x < y ? x : y;} TT T Abs(T x){return x < 0 ? -x : x;} int findSet(int x) { if(f[x]^x) f[x] = findSet(f[x]); return f[x]; } void unionSet(int u,int v){f[findSet(u)] = findSet(v);} struct node { int val,ID; bool operator < (const node &px)const{ if(val^px.val) return val < px.val; return ID < px.ID; } }; set<node> s; int 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(n&1) ++n,sg = 1; for(int i = 1;i <= n;++ i) f[i] = i,od[i] = i; sort(od+1,od+n+1,[](int x,int y){ return a[x] < a[y]; }); n >>= 1; for(int i = 1;i <= n;++ i) s.insert(node{a[od[i<<1]]-a[od[(i<<1)-1]],i}); while(s.size() > 1) { auto it1 = s.begin(),it2 = s.end(); --it2; unionSet(it1->ID,it2->ID+n); unionSet(it1->ID+n,it2->ID); node ne = node{it2->val-it1->val,it2->ID}; s.erase(it2); s.erase(s.begin()); s.insert(ne); } for(int i = 1;i <= n;++ i) if(findSet(i)^findSet(1)) ans[od[i<<1]] = 1; else ans[od[(i<<1)-1]] = 1; n <<= 1; printf("NP-Hard solved\n"); for(int i = 1;i <= n - sg;++ i) { if(ans[i]) Put(1); else Put(-1); putchar(i == (n-sg) ? '\n' : ' '); } return 0; }