Cod sursa(job #329898)

Utilizator MarcvsHdrMihai Leonte MarcvsHdr Data 7 iulie 2009 23:57:18
Problema Xor Max Scor 15
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.3 kb
# include <stdio.h>
# include <stdlib.h>

const long int MAXN=100000;
const long int MAXNRB=21;

typedef struct NOD
        {
        long int start;
        NOD *next[2];
        };

NOD *root;

long int n,nrb=0,sol_sum,sol_start,sol_end,swaps[MAXNRB+1],v[MAXN+1];

long int nrbiti(long int a)
{
    if (a==0) return 0;
    return 1+nrbiti(a/2);
}

void citire()
{
     FILE *f=fopen("xormax.in","r");
     fscanf(f,"%ld",&n);
     long int i;
     for (i=1;i<=n;i++)
         {
         fscanf(f,"%ld",&v[i]);
         if (nrbiti(v[i])>nrb) nrb=nrbiti(v[i]);
         }
     fclose(f);
}

void scrie()
{
     FILE *g=fopen("xormax.out","w");
     fprintf(g,"%ld %ld %ld\n",sol_sum,sol_start,sol_end);
     fclose(g);
}

NOD* insert_trie(NOD *root, long int start, long int number, long int bitno)
{
     if (bitno==0) 
        {
        root->start=start;
        return root;
        }
     int dir;
     //tre' sa aflam directia de deplasare
     if (number&(1<<(bitno-1))) dir=1;
     else dir=0;
     dir^=swaps[bitno];
     //verificam daca tre' sa ne deplasam in null
     if (root->next[dir]==NULL)
        {
        NOD *p=(NOD*) malloc(sizeof(NOD));
        p->start=-1;
        p->next[0]=NULL;
        p->next[1]=NULL;
        root->next[dir]=p;
        }
     root->next[dir]=insert_trie(root->next[dir],start,number,bitno-1);
     return root;
}

void find_max(NOD *root,long int bitno, long int *sol_sum_loc, long int *sol_start_loc)
{
     if (bitno==0) *sol_start_loc=root->start;
     else
         {
         long int dir=1;
         if (swaps[bitno]) dir=0;
         //incerci sa inaintezi in directia aleasa
         if (root->next[dir]!=NULL)
            {
            (*sol_sum_loc)+=1<<(bitno-1);
            find_max(root->next[dir],bitno-1,sol_sum_loc,sol_start_loc);
            }
         else
             find_max(root->next[1-dir],bitno-1,sol_sum_loc,sol_start_loc);
         }
}

void calculeaza()
{
     long int i,nrc,bit; long int sol_sum_loc,sol_start_loc;
     root=(NOD*) malloc(sizeof(NOD));
     root->start=-2;
     root->next[0]=NULL;
     root->next[1]=NULL;
     root=insert_trie(root,i,0,nrb);
     for (i=1;i<=n;i++)
         {
         //tre' sa refaci swaps
         nrc=v[i];
         for (bit=1;bit<=nrb;bit++)
             {
                swaps[bit]^=(nrc&1);
                nrc>>=1;
             }
         //tre' sa introduci acuma noua suma in trie
         nrc=v[i];
         root=insert_trie(root,i,v[i],nrb);
         //tre' sa scoti maximul
         sol_sum_loc=0;
         sol_start_loc=0;
         find_max(root,nrb,&sol_sum_loc,&sol_start_loc);
         //         printf("Suma %ld Start %ld-%ld \n",sol_sum_loc,sol_start_loc,i);
         //                fflush(stdin);
         //              getchar();
         if (sol_sum_loc>sol_sum || (sol_sum_loc==sol_sum&&sol_start_loc>sol_start))
            {
            sol_sum=sol_sum_loc;
            sol_start=sol_start_loc;
            sol_end=i;
            }
         }
}


         /*
         printf("Arbore: %ld\n",v[i]);
         postfix(root,0,' ');
         fflush(stdin);
         getchar();
         */

int main()
{
    citire();
    sol_sum=v[1];sol_start=1;sol_end=1;
    calculeaza();
    scrie();
    return 0;
}