Cod sursa(job #393591)

Utilizator perticas_catalinperticas catalin perticas_catalin Data 9 februarie 2010 18:20:36
Problema Ghiozdan Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.93 kb
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>

using namespace std;

#define PB push_back
#define GM 75005
#define NM 20005
#define inf 30000

int N,G,gmax;

short int P[GM],D[GM],E[GM];

int CATE[205];

short int B[GM][16],R[GM][16][2],A[GM][2];

int IND[1005],ob[NM];

vector<int> V;

inline void PD(int cat)
{
     for(int j=0;j<cat;++j)
     {
        int st=0,dr=-1;
             
        for(int k=0;k*cat+j<=G;++k)  
        {
             
           while((st<=dr) && (k*cat+j-IND[st])>CATE[cat]*cat) ++st;
             
           int val_cur=P[k*cat+j];
             
           if(val_cur!=inf)
           {
              while((st<=dr) && (val_cur<=P[IND[dr]]+(k*cat+j-IND[dr])/cat)) --dr;
            
              ++dr;
              IND[dr]=k*cat+j;  
           }   
             
           if(st<=dr) 
           {
              D[k*cat+j]=P[IND[st]]+(k*cat+j-IND[st])/cat;
              E[k*cat+j]=(k*cat+j-IND[st])/cat;
           }   
           else D[k*cat+j]=inf;
              
       }   
    }       
}

int main()
{
    int g;
    
    freopen("ghiozdan.in","r",stdin);
    freopen("ghiozdan.out","w",stdout);
    
    scanf("%d %d",&N,&G);
    
    for(int i=1;i<=N;++i)
    {
       scanf("%d",&g);
       gmax=max(gmax,g); 
       
       if(!CATE[g]) V.PB(g);    
       ++CATE[g];
    }
    
    N=V.size();
    
    int sq=(int)sqrt(N);
    
    V.PB(0);
    
    sort(V.begin(),V.end());
    
    int dim=0;
    
    for(int i=1;i<=G;++i)
    {
       A[i][0]=inf;
       B[i][0]=inf;
    }
    
    for(int i=1;i<=N;++i)
    {
       int cur=i%2;
       int prev=!cur;
       
       int cat=V[i];
       
       for(int j=0;j<=G;++j)
          A[j][cur]=inf;
       
       for(int j=0;j<cat;++j)
       {
          int st=0,dr=-1;
               
          for(int k=0;k*cat+j<=G;++k)  
          {
             //scoateri
             
             while((st<=dr) && (k*cat+j-IND[st])>CATE[cat]*cat) ++st;
             
             //inserari   
             
             int val_cur=A[k*cat+j][prev];
             
             if(val_cur!=inf)
             {
                while((st<=dr) && (val_cur<=A[IND[dr]][prev]+(k*cat+j-IND[dr])/cat)) --dr;
             
                ++dr;
                IND[dr]=k*cat+j;  
             }   
             
             if(st<=dr) A[k*cat+j][cur]=A[IND[st]][prev]+(k*cat+j-IND[st])/cat;
             else A[k*cat+j][cur]=inf;
              
          }   
       }     
       
       if(i%sq==0)
       {
          ++dim;
          for(int j=0;j<=G;++j) B[j][dim]=A[j][cur];        
       }   
    }
    
    int ind=G;
    
    while(A[ind][N%2]==inf) --ind;
    
    int ans=A[ind][N%2];
    
    printf("%d %d\n",ind,ans);
    
    int poz=ind;
    
    if(N%sq==0) --dim;
    
    int indi=N;
    
    int d=0;
    
    for(int l=dim;l>=0;--l)
    {
        for(int j=0;j<=G;++j)
           R[j][0][0]=B[j][l];
        
        for(int i=l*sq+1,ii=1;i<=min((l+1)*sq,N);++i,++ii)
        {
           for(int j=0;j<=G;++j)
              P[j]=R[j][ii-1][0];
           
           PD(V[i]);
           
           for(int j=0;j<=G;++j)
           {
              R[j][ii][0]=D[j];
              R[j][ii][1]=E[j];
           }        
        }     
        
        int indii=indi%sq;
        
        if(indii==0) indii=sq;   
        
        while(indii)
        {
           for(int j=1;j<=R[poz][indii][1];++j)
              ob[++d]=V[indi];
            
           poz-=(R[poz][indii][1]*V[indi]); 
              
           --indi;
           --indii;
        }
    }
    
   // sort(ob+1,ob+d+1);
    
    int sum=0;
    
    for(int i=1;i<=d;++i)
    {
       printf("%d\n",ob[i]);
       sum+=ob[i];
    }     
    
    //printf("%d %d",sum,d);
        
    return 0;
}