Cod sursa(job #254655)

Utilizator toni2007Pripoae Teodor Anton toni2007 Data 7 februarie 2009 13:35:01
Problema Cuburi2 Scor 50
Compilator cpp Status done
Runda Stelele Informaticii 2009, clasele 9-10, ziua 2 Marime 3.04 kb
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <bitset>

using namespace std;

const int maxN = 250001;
const long long oo = 1LL << 60;

long long Sum[maxN], Sum2[maxN], InvSum[maxN], InvSum2[maxN];
int V[maxN], N, M;

inline long long min(long long a, long long b){
	if (a < b)
		return a;
	return b;
}

long long SumaStg(int x, int y){
	return (Sum2[y] - Sum2[x - 1]) - 1LL * (y - x + 1) * Sum[x - 1];
}
long long SumaDr(int x, int y){
	return (InvSum2[x] - InvSum2[y + 1]) - 1LL * (y - x + 1) * InvSum[y + 1];
}

inline long long SumaPe(int a, int b, int i){
	int nr;
	long long st, dr;
	if (i == a)
		return SumaDr(a + 1, b);
	if (i == b)
		return SumaStg(a, b - 1);
	st = SumaStg(a, i - 1);
	dr = SumaDr(i + 1, b);
	//printf("(%d %d %d %lld %lld)\n",a, b, i, st, dr);
	return st + dr;
}
void baga_brut(int a, int b){
	int i, nr, poz;
	long long st, dr, minim = oo, x;

	nr = b - a;

	for (i = a ; i <= b; ++i){
		x = SumaPe(a, b, i);
		if (x < minim){
			minim = x;
			poz = i;
		}
	}
	printf("%d %lld\n", poz ,minim);
}


void baga_marfa(int a, int b){
    int i, x, inter = (b - a + 1), poz = 0, mid;
    long long minim = oo, f;
    bitset<maxN> B;
    srand(time(NULL));
    mid = N / 2;
    /*if (a <= mid && b <= mid){
        printf("%d %lld\n", b, SumaPe(a, b, b));
    }
    else if (a >= mid && b >= mid){
        printf("%d %lld\n", a, SumaPe(a, b, a));
    }
    else{*/
        mid = N / 2;
        for (i = 1; i <= 100 && i <= inter; ++i){
            x = rand() % inter + a;
            while (B[x])
                x = rand() % inter + a;
            f = SumaPe(a, b, x);
            if (f < minim){
                minim = f;
                poz = x;
            }
            B[x] = true;
        }
        /*f = search(a, b, i, x);
        if (f < minim){
            minim = f;
            poz = x;
        }*/
        for (i = max(a, mid - 50); i <= min(mid + 50, b); ++i){
            f = SumaPe(a, b, i);
            if (f < minim){
                minim = f;
                poz = i;
            }
        }

        for (i = max(poz - 50, a); i <= min(poz + 50, b); ++i){
            f = SumaPe(a, b, i);
            if (f < minim){
                minim = f;
                poz = i;
            }
        }
        inter = 200;
        for (i = 1; i <= 30; ++i){
            x = rand() % inter + poz - 50;
            while (B[x])
                x = rand() % inter + poz - 50;
            f = SumaPe(a, b, x);
            if (f < minim){
                minim = f;
                poz = x;
            }
            B[x] = true;
        }
        printf("%d %lld\n", poz, minim);
    //}
}
int main(){
	int i, a, b;

	freopen("cuburi2.in", "r", stdin);
	freopen("cuburi2.out", "w", stdout);

	scanf("%d%d", &N, &M);

	for (i = 1; i <= N; ++i){
		scanf("%d", &V[i]);
		Sum[i] = Sum[i - 1] + V[i];
		Sum2[i] = Sum2[i - 1] + Sum[i];
	}
	for (i = N; i; --i){
		InvSum[i] = InvSum[i + 1] + V[i];
		InvSum2[i] = InvSum2[i + 1] + InvSum[i];
	}
	while (M --){
		scanf("%d%d", &a, &b);
        if (M <= 5000 && N <= 5000)
			baga_brut(a, b);
		else
			baga_marfa(a, b);
	}

}