Cod sursa(job #528567)

Utilizator vladiiIonescu Vlad vladii Data 2 februarie 2011 23:37:07
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.63 kb
#include <iostream>
#include <cstdio>
#include <cstring>
#include <deque>
using namespace std;
#define maxn 20010
#define maxg 75010
#define inf 999999999
#define pii pair<int, int>
#define pb push_back
#define mkp make_pair

int N, g, gmax, nmin;
int nr[210];
int A[2][maxg], B[2][maxg];
deque<pii> deq;
FILE *f1, *f2;

void solve(int st, int dr, int G) {
    int i, j, p, add;
    int mid = (st + dr) / 2;

    if(G == 0) return;
    if(st == dr) {
         int c = 0, sum = 0;
         while(c < nr[st] && sum + st <= G) {
              fprintf(f2, "%d\n", st);
              c ++;
              sum += st;
         }
         return;
    }

    for(i=1; i<=G; i++) {
         A[0][i] = inf;
    }

    for(i=st; i<=dr; i++) {
         if(!nr[i]) continue;

         //folosesc greutatile i
         for(j=1; j<=G; j++) {
              A[1][j] = inf;
         }

         for(j=0; j<i; j++) {
              //(j, j + i, j + 2*i, ..., j + nr[i]*i)
              deq.clear(); add = 0;

              deq.pb( mkp(j, 0) );

              for(p=j; p<=G; p+=i) {
                   //elimin din deque elementele necorespunzatoare
                   int tm = (p - j) / i;
                   while(deq.size() && deq.front().second < tm - nr[i]) {
                        deq.pop_front();
                   }

                   //aflu A[1][p]
                   A[1][p] = A[0][ deq.front().first ] - deq.front().second + tm;

                   if(i <= mid) { B[1][p] = p; }
                   else { B[1][p] = B[0][ deq.front().first ]; }

                   //adaug A[0][p + i] in deq
                   add ++;
                   while(deq.size() && A[0][ deq.back().first ] - deq.back().second >= A[0][p + i] - add) {
                        deq.pop_back();
                   }
                   deq.pb( mkp(p + i, tm + 1) );
              }
         }

         for(j=1; j<=G; j++) {
              A[0][j] = A[1][j];
              B[0][j] = B[1][j];
         }
    }

    if(st == 1 && dr == 200) {
         for(i=G; i>=1; i--) {
              if(A[0][i] < inf) {
                   gmax = i; nmin = A[0][i];
                   break;
              }
         }

         fprintf(f2, "%d %d\n", gmax, nmin);
    }

    for(i=G; i>=0; i--) {
         if(A[0][i] < inf) {
              gmax = i; break;
         }
    }

    int val = B[0][gmax];

    solve(st, mid, val);
    solve(mid+1, dr, G - val);
}

int main() {
    f1=fopen("ghiozdan.in", "r"), f2=fopen("ghiozdan.out", "w");
    int i, p;

    fscanf(f1, "%d %d\n", &N, &g);
    for(i=1; i<=N; i++) {
         fscanf(f1, "%d\n", &p);
         nr[p] ++;
    }

    solve(1, 200, g);

    fclose(f1); fclose(f2);
    return 0;
}