AkashCode77's blog

By AkashCode77, history, 9 months ago, In English

So last day I participated in Leetcode Biweekly Contest 124. And as stupid as I am, I misread the first problem and made it harder. Link to the first problem.

The problem statement is as follows:


Given an array of integers called nums, you can perform the following operation while nums contains at least 2 elements:

  • Choose the first two elements of nums and delete them.
  • The score of the operation is the sum of the deleted elements.

Your task is to find the maximum number of operations that can be performed, such that all operations have the same score.

Return the maximum number of operations possible that satisfy the condition mentioned above.


I thought that before we delete the elements, we could arrange nums in any order we like. Now it makes me wonder is it a known problem with the added constraint that we can arrange the array in any order to maximize the sum? Moreover, I'm unable to think of a solution with the added constraint. I want to know the optimal way of solving this problem with the added constraint.

Thanks!

  • Vote: I like it
  • 0
  • Vote: I do not like it

»
9 months ago, # |
Rev. 2   Vote: I like it +12 Vote: I do not like it

Just now I think of $$$n^3$$$ idea using 2 pointers method:

  1. Sort $$$a$$$
  2. Choose initial pointers $$$i, j, i<j$$$, $$$a_i+a_j$$$ will be the constant sum
  3. Repeat this step:
    • Increment $$$i$$$ by $$$1$$$, decrement $$$j$$$ by $$$1$$$
    • Adjust $$$i$$$ and $$$j$$$ until the constant sum is reached once again (like solution to 2SUM)

Then the answer is the max number of times step 3 is repeated across all initial $$$(i, j)$$$

Likely some optimisation is possible.

»
9 months ago, # |
Rev. 5   Vote: I like it +3 Vote: I do not like it

$$$1 <= N, a[i] <= 10^5$$$

$$$O(max(a)sqrt(max(a))$$$

#pragma GCC optimize("O2")
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx,avx2,fma")
#pragma GCC target("sse4,popcnt,abm,mmx")

#include <bits/stdc++.h>

#define out(x) cout << #x << '=' << (x) << endl
#define out2(x, y) cout << #x << '=' << (x) << ',' << #y << '=' << (y) << endl 
#define no do { cout << "No" << endl; return; } while(0)
#define yes do { cout << "Yes" << endl; return; } while (0)
#define lowbit(x) ((x) & -(x))

using namespace std;

using ll = long long;

const ll inf = 0x3f3f3f3f3f3f3f3fLL;
const int infi = 0x3f3f3f3f;

template<typename T> ostream & operator << (ostream &out,const set<T>&obj){out<<"set(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}
template<typename T1,typename T2> ostream & operator << (ostream &out,const map<T1,T2>&obj){out<<"map(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<it->first<<": "<<it->second;out<<")";return out;}
template<typename T1,typename T2> ostream & operator << (ostream &out,const pair<T1,T2>&obj){out<<"<"<<obj.first<<", "<<obj.second<<">";return out;}
template<typename T> ostream & operator << (ostream &out,const vector<T>&obj){out<<"vector(";for(auto it=obj.begin();it!=obj.end();it++) out<<(it==obj.begin()?"":", ")<<*it;out<<")";return out;}


const int maxn = 1e5;

const int B = sqrt(maxn) / __lg(maxn) / 2;

int cnt[maxn + 1], ans[maxn * 2 + 1];
vector<int> cntv[B + 1];

using LL = ll;

const int MAXN = 3 * 1e5 + 10, P = 998244353, G = 3, Gi = 332748118;

int limit, r[MAXN];
LL a[MAXN], b[MAXN];

inline LL fastpow(LL a, LL k) {
	LL base = 1;
	while(k) {
		if(k & 1) base = (base * a ) % P;
		a = (a * a) % P;
		k >>= 1;
	}
	return base % P;
}

inline void NTT(LL *A, int type) {
	for(int i = 0; i < limit; i++) 
		if(i < r[i]) swap(A[i], A[r[i]]);
	for(int mid = 1; mid < limit; mid <<= 1) {	
		LL Wn = fastpow( type == 1 ? G : Gi , (P - 1) / (mid << 1));
		for(int j = 0; j < limit; j += (mid << 1)) {
			LL w = 1;
			for(int k = 0; k < mid; k++, w = (w * Wn) % P) {
				 int x = A[j + k], y = w * A[j + k + mid] % P;
				 A[j + k] = (x + y) % P,
				 A[j + k + mid] = (x - y + P) % P;
			}
		}
	}
}
void ntt(int N, int M) {
    int L = 0;
    limit = 1;
	while(limit <= N + M) limit <<= 1, L++;
	for(int i = 0; i < limit; i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (L - 1));	
	NTT(a, 1); NTT(b, 1);
	for(int i = 0; i < limit; i++) a[i] = (a[i] * b[i]) % P;
	NTT(a, -1); NTT(b, -1);
	LL inv = fastpow(limit, P - 2);
	for(int i = 0; i <= N + M; i++) {
		a[i] = a[i] * inv % P;
		b[i] = b[i] * inv % P;
	}
}

void solve() {
    int n;
    cin >> n;
    
    for (int i = 1; i <= n; i++) {
        int a;
        cin >> a;
        cnt[a]++;
    }
    //out(B);
    //B = sqrt(maxn) / logmaxn
    //part1 maxn * sqrt(maxn)
    //part2 maxn * logmaxn ^ 2
    
    vector<int> other;
    for (int i = 1; i <= maxn; i++) {
        if (cnt[i] <= B) {
            cntv[cnt[i]].push_back(i);
        } else {
            other.push_back(i);
        }
    }
    
    //part2
    for (int x : other) {
        b[x] += 2;
        for (int y : other) {
            ans[x + y] += min(cnt[x], cnt[y]);
        }
    }
    
    //part1
    for (int i = B; i > 0; i--) {
        for (int x : cntv[i]) {
            b[x]++;
            a[x]++;
        }
        ntt(maxn, maxn);
        for (int j = 1; j <= maxn * 2; j++) {
            ans[j] += a[j] * i;
        }
        memset(a, 0, sizeof(a));
        for (int x : cntv[i]) {
            b[x]++;
        }
    }
    
    int res = 0;
    for (int i = 1; i <= maxn * 2; i++) {
        res = max(res, ans[i] / 2);
    }
    cout << res << endl;
}

int main(void) {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int t = 1;
	//cin >> t;
    
    while (t--) {
    	solve(); 
	}
}
  • »
    »
    9 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    You just blew my mind. Thank you.

  • »
    »
    9 months ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    I'm really interested in it, what is use of "number theoretic transform"?