Cod sursa(job #973610)

Utilizator claudiumihailClaudiu Mihail claudiumihail Data 14 iulie 2013 20:42:19
Problema Stalpi Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 8.22 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

#define MAXN 100002

using namespace std;

struct Pole
{
    Pole(int xx, int l, int r, int c) :
        x(xx),
        Left(l),
        Right(r),
        Cost(c)
    {}

    int x = 0;
    int Left = 0;
    int Right = 0;
    int Cost = 0;
};

ostream& operator << (ostream& os, Pole pole)
{
    os << pole.x << " " << pole.Left << " " << pole.Right << " " << pole.Cost;
    return os;
}

bool operator < (const Pole& lhs, const Pole& rhs)
{
    return lhs.x < rhs.x;
}

pair<int, int> vRightSortedPoles[MAXN];
long long costs[MAXN];


#define MAX_SIZE 100001
#define GET_0_BASED_INDEX_PARENT(index) (((index)-1-!((index)%2)) / 2)
#define LEFT_SUBTREE(index) (((index)<<1)+1)
#define RIGHT_SUBTREE(index) (((index)+1)<<1)

using namespace std;

typedef unsigned int uint32;

template<class T, class Compare = less<T> >
class IntervalTree
{
public:

	IntervalTree(const int size, const T& defaultValue) :
		intervalSize(size)
	{
		vValues = (T*)malloc((size+1)*sizeof(T));
		vValues[size] = defaultValue;
		intervalTree = (int*)calloc((4*size+2), sizeof(int));
	}
	
	inline void Update(const int index, const T& value)
	{
		vValues[index] = value;
		UpdateIndex(index);
	}
	
	inline void Update(const int index)
	{
		UpdateIndex(index);
	}
	
	inline void UpdateIndex(const int index)
	{
		int left = 0, right = intervalSize-1;
		int intervalTreeIndex = 0;
		
		while (left < right)
		{
			const int mid = left + (right-left)/2;
			if (index <= mid)
			{
				intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
				right = mid;
			}
			else
			{
				intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
				left = mid+1;
			}
		}
		
		if (left == index)
		{
			intervalTree[intervalTreeIndex] = index;
			
			int parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);

			while(parent >= 0)
			{
				if (compare(vValues[intervalTree[LEFT_SUBTREE(parent)]], vValues[intervalTree[RIGHT_SUBTREE(parent)]]))
				{
					intervalTree[parent] = intervalTree[LEFT_SUBTREE(parent)];
				}
				else
				{
					intervalTree[parent] = intervalTree[RIGHT_SUBTREE(parent)];
				}
				
				intervalTreeIndex = parent;
				parent = GET_0_BASED_INDEX_PARENT(intervalTreeIndex);
			}
		}
	}

	inline int QueryIndex(const int l, const int r) const
	{
		int intervalTreeIndex = 0;
		int left = 0, right = intervalSize-1;
		
		if (l == r)
		{
			return QueryElementaryInterval(l);
		}

		int mid = left + (right-left)/2;
		while (r <= mid || l > mid)
		{
			if (r <= mid)
			{
				right = mid;
				intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
			}
			else if (l > mid)
			{
				left = mid+1;
				intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
			}
			
			mid = left + (right-left)/2;
		}
		
		const int leftIndex = QueryLeftSubInterval(left, mid, l, LEFT_SUBTREE(intervalTreeIndex));
		const int rightIndex = QueryRightSubInterval(mid+1, right, r, RIGHT_SUBTREE(intervalTreeIndex));
		
		if (compare(vValues[leftIndex], vValues[rightIndex]))
		{
			return leftIndex;
		}

		return rightIndex;
	}
	
	inline T& QueryValue(const int l, const int r)
	{
		return vValues[QueryIndex(l,r)];
	}
	
	inline const T& QueryValue(const int l, const int r) const
	{
		return vValues[QueryIndex(l,r)];
	}

	inline T& GetValueAt(const int index)
	{
		return vValues[index];
	}
	
	inline const T& GetValueAt(const int index) const
	{
		return vValues[index];
	}

private:

	inline int QueryElementaryInterval(const int index) const
	{
		int left = 0, right = intervalSize-1;
		int intervalTreeIndex = 0;
		
		while (left < right)
		{
			const int mid = left + (right-left)/2;
			if (index <= mid)
			{
				intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
				right = mid;
			}
			else
			{
				intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
				left = mid+1;
			}
		}
		
		if (left == index)
		{
			return intervalTree[intervalTreeIndex];
		}
		
		return intervalTree[intervalSize];
	}

	inline int QueryLeftSubInterval(int left, int right, const int finalLeft, int intervalTreeIndex) const
	{
		int foundIndex = intervalSize;
		
		while (finalLeft != left)
		{
			const int mid = left + (right-left)/2;
			
			if (finalLeft <= mid)
			{
				if (compare(vValues[intervalTree[RIGHT_SUBTREE(intervalTreeIndex)]], vValues[foundIndex]))
				{
					foundIndex = intervalTree[RIGHT_SUBTREE(intervalTreeIndex)];
				}
				
				intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
				right = mid;
			}
			else
			{
				left = mid+1;
				intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
			}
		}
		
		if (compare(vValues[intervalTree[intervalTreeIndex]], vValues[foundIndex]))
		{
			foundIndex = intervalTree[intervalTreeIndex];
		}
		
		return foundIndex;
	}

	inline int QueryRightSubInterval(int left, int right, const int finalRight, int intervalTreeIndex) const
	{	
		int foundIndex = intervalSize;
		
		while (finalRight != right)
		{
			const int mid = left + (right-left)/2;

			if (finalRight > mid)
			{
				if (compare(vValues[intervalTree[LEFT_SUBTREE(intervalTreeIndex)]], vValues[foundIndex]))
				{
					foundIndex = intervalTree[LEFT_SUBTREE(intervalTreeIndex)];
				}

				intervalTreeIndex = RIGHT_SUBTREE(intervalTreeIndex);
				left = mid+1;
			}
			else
			{
				right = mid;
				intervalTreeIndex = LEFT_SUBTREE(intervalTreeIndex);
			}
		}
		
		if (compare(vValues[intervalTree[intervalTreeIndex]], vValues[foundIndex]))
		{
			foundIndex = intervalTree[intervalTreeIndex];
		}
		
		return foundIndex;
	}

	Compare			compare;
	const int		intervalSize;
	int				*intervalTree;
	T				*vValues;
};

int main()
{
    int n;
    vector<Pole> vPoles;
    fstream fin("stalpi.in", fstream::in);
    fstream fout("stalpi.out", fstream::out);

    fin >> n;
    //cout << n << endl;

    vPoles.reserve(n+2);

    vPoles.push_back(Pole(- (1 << 30), 0, 0, 0));
    for (int i=0; i<n; ++i)
    {
        int x, l, r, c;
        fin >> x >> c >> l >> r;
        
        vPoles.push_back(Pole(x, l, r, c));
    }
    
    sort(begin(vPoles), end(vPoles));
    
    for (int i=0; i<n; ++i)
    {
        vRightSortedPoles[i] = make_pair(vPoles[i+1].x + vPoles[i+1].Right, i+1);
    }
    
    sort(begin(vRightSortedPoles), begin(vRightSortedPoles) + n);

    int maxPoleX = vRightSortedPoles[n-1].first + 1;
    
    vPoles.push_back(Pole(maxPoleX + 1, 0, 0, 0));
    
    ostream_iterator<int> itOut(cout, " ");
    ostream_iterator<Pole> itOutPoles(cout, "\n");
    
    /*copy_n(begin(vPoles), n + 2, itOutPoles);
    cout << endl;
    
    for (int i=0; i<n; ++i)
    {
        cout << vRightSortedPoles[i].first << " " << vRightSortedPoles[i].second << endl;
    }
    cout << endl;*/
    
    for (int i=1; i<=n; ++i)
    {
        costs[i] = 1LL << 61;
    }
    
    IntervalTree<long long, less<long long> > intervalTree(n+2, 1LL << 61);
    
    intervalTree.Update(0, 0);
    for (int i=1; i<=n; ++i)
    {
        intervalTree.Update(i, 1LL << 61);
    }
    
    for (int i=0; i<n; ++i)
    {
        long long minVal = 1LL << 61;
        
        Pole pole(vPoles[vRightSortedPoles[i].second].x - vPoles[vRightSortedPoles[i].second].Left, 0, 0, 0);
        int L = lower_bound(begin(vPoles), end(vPoles), pole) - begin(vPoles) - 1;
        
        pole = Pole(vRightSortedPoles[i].first + 1, 0, 0, 0);
        int R=lower_bound(begin(vPoles), end(vPoles), pole) - begin(vPoles) - 1;
        
        minVal = intervalTree.QueryValue(L, n) + vPoles[vRightSortedPoles[i].second].Cost;
        
        /*for (int k=L; k<=R; ++k)
        {
            minVal = min(minVal, costs[k] + vPoles[vRightSortedPoles[i].second].Cost);
        }*/
        
        //cout << L << " " << R << endl;
        
        costs[R] = min(costs[R], minVal);
        intervalTree.Update(R, costs[R]);

        /*for (int k=1; k<=R; ++k)
        {
            costs[k] = min(costs[k], minVal);
        }*/
    }

    /*for (int i=0; i<=n; ++i)
    {
        cout << costs[i] << " ";
    }
    cout << endl;*/
    
    fout << costs[n] << "\n";

    return 0;
}