Cod sursa(job #2919363)

Utilizator KarimElSheikhKarim Elsheikh KarimElSheikh Data 16 august 2022 21:46:16
Problema Ghiozdan Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 14.1 kb
#pragma GCC target ("avx2")
#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//using namespace __gnu_pbds;
using namespace std;

typedef long long ll;
typedef pair<int, int> ii;
typedef pair<ll, ll> pll;
typedef vector<ii> vii;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef unsigned int uint;
typedef unsigned long long ull;
//typedef tree<int, null_type, std::less<>, rb_tree_tag, tree_order_statistics_node_update> indexed_set;
//typedef tree<pair<int, int>, null_type, greater<pair<int, int>>, rb_tree_tag, tree_order_statistics_node_update> oset;

#define er "\n"

#define rep(i, x, y)  for(int i = x; i < y; ++i)
#define Rep(i, x, y)  for(int i = x; i <= y; ++i)
#define sRep(i, x, y) for(int i = x; i >= y; --i)
#define ite(it,s) for(auto it = s.begin(); it!=s.end(); ++it)
	
#define getBit(x,i) (x&(1<<i))
#define setBit(x,i) (x|(1<<i))
#define mid(L,R) ((L+R)/2)
#define mem(A,N) memset(A,N,sizeof(A))
#define sz(x) ((int)(x).size())

#define all(v) v.begin(),v.end()
#define rev(v) reverse(v.begin(),v.end())
#define Sort(x) sort(x.begin(),x.end());

// vector/deque
#define pb push_back
#define pf push_front
#define ppb pop_back
#define ppf pop_front

// pairs
#define mp make_pair
#define fi first
#define se second

// Less common loops
#define srep(i, x, y) for(int i = x; i > y; --i)
#define rep2(i, x, y)  for(int i = x; i < y; i+=2)
#define Rep2(i, x, y)  for(int i = x; i <= y; i+=2)
#define sRep2(i, x, y) for(int i = x; i >= y; i-=2)
#define srep2(i, x, y) for(int i = x; i > y; i-=2)

#define sumsTo(s) ((int)((-1+sqrt(1+8*s))/2))
#define inBounds(x,y) (x >= 0 && x < n && y >= 0 && y < m)
#define isInt(x) ((int) floor(x)==x)

#define yes() (cout << "yes\n");
#define no() (cout << "no\n");
#define Yes() (cout << "YES\n");
#define No() (cout << "NO\n");
#define yes2() (cout << "Yes\n");
#define no2() (cout << "No\n");

#define linf 1000000000000000001LL
#define inf 1000000001
#define mod 1000000007
#define eps 1e-9
#define Pi 3.14159265358979323846

// Debug
#ifndef ONLINE_JUDGE
#define dump(x)  cerr << #x << "=" << (x) << endl;
#define write(x) cerr << #x << "=" << (x) << ", ";
#define writeSet(s) cerr << #s << "= "; for(auto it = s.begin(); it!=s.end(); it++) (it==s.begin())? cerr << *it : cerr << ' ' << *it;
#define dumpSet(s) cerr << #s << "= "; for(auto it = s.begin(); it!=s.end(); it++) (it==s.begin())? cerr << *it : cerr << ' ' << *it; cerr << endl;
#define writeMap(s) cerr << #s << "= "; for(auto it = s.begin(); it!=s.end(); it++) (it==s.begin())? cerr << it->first << ',' << it->second : cerr << ' ' << it->first << ',' << it->second;
#define dumpMap(s) cerr << #s << "= "; for(auto it = s.begin(); it!=s.end(); it++) (it==s.begin())? cerr << it->first << ',' << it->second : cerr << ' ' << it->first << ',' << it->second; cerr << endl;

// Debug - Printing loop counters (i,j,k,p)
#define writei cerr << "i = " << i << ".. ";
#define dumpi cerr << "i = " << i << endl;
#define writej cerr << "j = " << j << ".. ";
#define dumpj cerr << "j = " << j << endl;
#define writek cerr << "k = " << k << ".. ";
#define dumpk cerr << "k = " << k << endl;
#define writep cerr << "p = " << p << ".. ";
#define dumpp cerr << "p = " << p << endl;
#endif

//void __print(int x) {cerr << x;}                           string __strprint(int x) {return to_string(x);}                              
//void __print(long x) {cerr << x;}                          string __strprint(long x) {return to_string(x);}
//void __print(long long x) {cerr << x;}                     string __strprint(long long x) {return to_string(x);}
//void __print(unsigned x) {cerr << x;}                      string __strprint(unsigned x) {return to_string(x);}
//void __print(unsigned long x) {cerr << x;}                 string __strprint(unsigned long x) {return to_string(x);}
//void __print(unsigned long long x) {cerr << x;}            string __strprint(unsigned long long x) {return to_string(x);}
//void __print(float x) {cerr << x;}                         string __strprint(float x) {return to_string(x);}
//void __print(double x) {cerr << x;}                        string __strprint(double x) {return to_string(x);}
//void __print(long double x) {cerr << x;}                   string __strprint(long double x) {return to_string(x);}
//void __print(char x) {cerr << '\'' << x << '\'';}          string ___strprint(char x) {return "\'" + string(1,x) + "\'";}
//void __print(const char *x) {cerr << '\"' << x << '\"';}   string __strprint(const char *x) {return "\"" + string(x) + "\"";} 
//void __print(const string &x) {cerr << '\"' << x << '\"';} string __strprint(const string &x) {return "\"" + x + "\"";} 
//void __print(bool x) {cerr << (x ? "true" : "false");}     string ___strprint(bool x) {return (x ? "true" : "false");}
//
//template<typename T, typename V>
//void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ','; __print(x.second); cerr << '}';}
//template<typename T>
//void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), __print(i); cerr << "}";}
//void _print() {cerr << "]\n";}
//template <typename T, typename... V>
//void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
//
//template<typename T, typename V>
//string __strprint(const pair<T, V> &x) {string build="{"; build+=__strprint(x.first); build+=","; build+=__strprint(x.second); return build+"}";}
//template<typename T>
//string __strprint(const T &x) {int f = 0; string build="{"; for (auto &i: x) build+=(f++ ? "," : ""), build+=__strprint(i); return build+"}";}
//string _strprint() {return "]";}
//template <typename T, typename... V>
//string _strprint (T t, V... v) {string build=__strprint(t); if (sizeof...(v)) build+=", "; return build+_strprint(v...);}

//string _strdebug(x...) (stringstream ss; ss<<"["<<#x<<"] = ["<<_strprint(x); return ss.str();)

//ostream& operator << (ostream& os, const ii& p) { return (os << '(' << p.first << ',' << p.second << ')'); }
template<typename T, typename V> pair<T, V> operator + (const pair<T, V>& p1, const pair<T, V>& p2) { return make_pair(p1.first+p2.first,p1.second+p2.second); }
//template<typename T> typename T::iterator min_map_element(T& m) { return min_element(m.begin(), m.end(), [](typename T::value_type& l, typename T::value_type& r) -> bool { return l.second < r.second; }); }
//template<typename T> typename T::iterator max_map_element(T& m) { return max_element(m.begin(), m.end(), [](typename T::value_type& l, typename T::value_type& r) -> bool { return l.second < r.second; }); }

// Print
#define printArray(a,x,y)  for(auto it = (a)+(x);      it != (a)+(y);   it++) (it==(a)+(x))     ? cout << *it : cout << ' ' << *it; cout << '\n';
#define PrintArray(a,x,y)  for(auto it = (a)+(x);      it != (a)+(y)+1; it++) (it==(a)+(x))     ? cout << *it : cout << ' ' << *it; cout << '\n';
#define sPrintArray(a,x,y) for(auto it = (a)+(x);      it != (a)+(y)-1; it--) (it==(a)+(x))     ? cout << *it : cout << ' ' << *it; cout << '\n';
#define printVector(x)     for(auto it = (x).begin();  it!=(x).end();   it++) (it==(x).begin()) ? cout << *it : cout << ' ' << *it; cout << '\n';
#define sprintVector(x)    for(auto it = (x).rbegin(); it!=(x).rend();  it++) (it==(x).rbegin())? cout << *it : cout << ' ' << *it; cout << '\n';
#define sPrintVector(x)    for(auto it = (x).rbegin(); it!=(x).rend();  it++) (it==(x).rbegin())? cout << *it : cout << ' ' << *it; cout << '\n'; // same as above one.
#define printSet(s)        for(auto it = s.begin();    it!=s.end();     it++) (it==(s).begin()) ? cout << *it : cout << ' ' << *it; cout << '\n';
#define sprintSet(s)       for(auto it = s.rbegin();   it!=s.rend();    it++) (it==(s).rbegin())? cout << *it : cout << ' ' << *it; cout << '\n';
#define printPairset(s)    for(auto it = (s).begin();  it!=(s).end();   it++) (it==(s).begin()) ? cout << '(' << it->first << ',' << it->second << ')' : cout << " {" << it->first << ',' << it->second << '}'; cout << '\n';
#define sprintPairset(s)   for(auto it = (s).rbegin(); it!=(s).rend();  it++) (it==(s).rbegin())? cout << '(' << it->first << ',' << it->second << ')' : cout << " {" << it->first << ',' << it->second << '}'; cout << '\n';

#define printArrayln(a,x,y) for(auto it = (a)+(x);     it != (a)+(y);   it++) (it==(a)+(x))      ? cout << *it : cout << '\n' << *it; cout << '\n';
#define PrintArrayln(a,x,y) for(auto it = (a)+(x);     it != (a)+(y)+1; it++) (it==(a)+(x))      ? cout << *it : cout << '\n' << *it; cout << '\n';
#define sPrintArrayln(a,x,y)  for(auto it = (a)+(x);     it != (a)+(y)-1; it++) (it==(a)+(x))      ? cout << *it : cout << '\n' << *it; cout << '\n';
#define printVectorln(x)    for(auto it = (x).begin();  it!=(x).end();   it++) (it==(x).begin()) ? cout << *it : cout << '\n' << *it; cout << '\n';
#define sprintVectorln(x)   for(auto it = (x).rbegin(); it!=(x).rend();  it++) (it==(x).rbegin())? cout << *it : cout << '\n' << *it; cout << '\n';
#define sPrintVectorln(x)   for(auto it = (x).rbegin(); it!=(x).rend();  it++) (it==(x).rbegin())? cout << *it : cout << '\n' << *it; cout << '\n'; // same as above one.
#define printSetln(s)       for(auto it = s.begin();    it!=s.end();     it++) (it==(s).begin()) ? cout << *it : cout << '\n' << *it; cout << '\n';
#define sprintSetln(s)      for(auto it = s.rbegin();   it!=s.rend();    it++) (it==(s).rbegin())? cout << *it : cout << '\n' << *it; cout << '\n';
#define printPairsetln(s)   for(auto it = (s).begin();  it!=(s).end();   it++) (it==(s).begin()) ? cout << '(' << it->first << ',' << it->second << ')' : cout << "\n{" << it->first << ',' << it->second << '}'; cout << '\n';
#define sprintPairsetln(s)  for(auto it = (s).rbegin(); it!=(s).rend();  it++) (it==(s).rbegin())? cout << '(' << it->first << ',' << it->second << ')' : cout << "\n{" << it->first << ',' << it->second << '}'; cout << '\n';

// Less common prints
#define sprintArray(a,x,y) for(auto it = (a)+(x);      it != (a)+(y);   it--) (it==(a)+(x))     ? cout << *it : cout << ' ' << *it; cout << '\n';
#define sprintArrayln(a,x,y) for(auto it = (a)+(x);      it != (a)+(y);   it--) (it==(a)+(x))    ? cout << *it : cout << '\n' << *it; cout << '\n';

ostringstream debug_sstr; string debug_str; vector<string> debug_strvec;
#ifndef ONLINE_JUDGE
#define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#define sdebug(x...) (debug_sstr<<"["<<#x<<"]=["<<_strprint(x),debug_str=debug_sstr.str(),debug_sstr=ostringstream(),debug_str)
#define sDebugVector(v,a,x,y) for(auto it = (a)+(x); it != (a)+(y)+1; it++) (it==(a)+(x)) ? debug_sstr << *it : debug_sstr << ' ' << *it; (debug_str=debug_sstr.str(),debug_sstr=ostringstream(),(v).push_back(debug_str))
#define sDebugVector2(v,a,x,y) debug_strvec = vector<string>(); for(auto it = (a)+(x); it != (a)+(y)+1; it++) debug_strvec.push_back(to_string(*it)); v.push_back(debug_strvec);
#else
#define debug(x...)
#endif

#ifndef OUTPUT_PATH
#define fout(x) fout;(&fout)->basic_ios<char>::rdbuf(cout.rdbuf());
#endif

// ***************** End Of Template ********************

int n, w;
int a[20000];
//tuple<int,int,int> ks[2][75001];
ii ks[75001];
ii ks2[75001];
ii ans;

vector<bool>* knapsack_(int startItem, int N, int startWeight, int W, int* a, int* ar) {
	if (startItem == N) return new vector<bool> ();
	if (N - startItem == 1) if (a[startItem] <= (W-startWeight)) return new vector<bool> {1}; else return new vector<bool> {0};
	
	memset(ks  + startWeight, 0, (W - startWeight + 1)*8);
	memset(ks2 + startWeight, 0, (W - startWeight + 1)*8);
//	Rep(i,startWeight,W) ks[i] = ks2[i] = mp(0,0);
	int mid = (startItem + N + 1) / 2;
	
	for (int i = startItem; i < mid; i++) {
		int weight = a[i];
		for (int j = W; j >= startWeight+weight; j--)
			ks[j] = max(ks[j], mp(ks[j-weight].fi+weight,ks[j-weight].se-1));
	}
	for (int i = N-1; i >= mid; i--) {
		int weight = a[i];
		for (int j = startWeight; j <= W-weight; j++)
			ks2[j] = max(ks2[j], mp(ks2[j+weight].fi+weight,ks2[j+weight].se-1));
	}
	
	ii bestSplitLength = mp(-inf,-inf); int bestSplitIdx = startWeight;
	for (int j = startWeight; j <= W; j++) {
		ii curSplit = ks[j] + ks2[j];
		if (curSplit > bestSplitLength) {
			bestSplitLength = curSplit; bestSplitIdx = j;
		}
		else if (curSplit == bestSplitLength && (abs(mid-j) < abs(mid-bestSplitIdx))) {
			bestSplitLength = curSplit; bestSplitIdx = j;
		}
	}
	if (N == n) ans = bestSplitLength;
		
	vector<bool>* v1 = knapsack_(startItem, mid,     startWeight, bestSplitIdx,     a,  ar);
	vector<bool>* v2 = knapsack_(n - N,     n - mid, w - W,       w - bestSplitIdx, ar, a);
	v1->insert(v1->end(),v2->rbegin(),v2->rend());
	return v1;
}

vector<bool>* knapsack(int startItem, int N, int startWeight, int W, int* a) {
	int ar[N]; for(int i = 0; i != N; i++) ar[i] = a[N-1-i];
	return knapsack_(startItem, N, startWeight, W, a, ar);
}

int main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	freopen("ghiozdan.in", "r", stdin);
	freopen("ghiozdan.out", "w", stdout);
	cin >> n >> w;
	rep(i,0,n) {
		cin >> a[i];
	}
	vector<bool>* x = knapsack(0,n,0,w,a);
	cout << ans.fi << ' ' << -ans.se;
	for (int i = 0; i != x->size(); i++) if ((*x)[i]) cout << '\n' << a[i];
	
	
//	sort(a,a+n);
//	set<int> s;
//	rep(i,0,n) s.insert(a[i]);
//	Rep(i,0,w) ks[0][i] = make_tuple(0,0,0);
//	int cur = 0, prv = 1;
//	int last = 0;
//	rep(i,0,n) {
//		int weight = a[i];
//		if (weight != last) { v.push_back(get<0>(ks[cur][w])); last = weight; }
//		swap(cur,prv);
//		Rep(j,weight,w) {
//			tuple<int,int,int> y = ks[prv][j-weight];
//			ks[cur][j] = max(ks[prv][j], make_tuple(get<0>(y)+weight, get<1>(y)-1, -weight));
//		}
//	}
//	v.push_back(get<0>(ks[cur][w]));
//	cout << get<0>(ks[cur][w]) << ' ' << -get<1>(ks[cur][w]) << endl;
//	printVector(v);
//	int i = v.size()-1;
//	auto it = --s.end();
//	int weightReached = get<0>(ks[cur][w]);
//	vi ans_v;
//	while (true) {
//		int weight = *it;
//		if (weightReached == v[i]) { i--; it--; if (i < 0) break; }
//		else {
//			weightReached -= weight;
//			ans_v.push_back(weight);
//		}
//	}
//	rev(ans_v);
//	printVector(ans_v);
	return 0;
}