1 条题解

  • 0
    @ 2021-6-15 14:22:00

    C++ :

    /*
     * ZJOI 2010 Day 1 Problem 3
     *
     * Author: Dong Zhou
     */
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    
    using namespace std;
    
    int n, K;
    int D[20005], C[20005], S[20005], W[20005];
    
    vector<pair<int, int> > events[20005];
    int opt[20005];
    int tree[65536], offset[65536];
    
    int answer;
    
    int binarySearch( int n, int A[], int key )
    {
    	int l = 0, r = n - 1;
    
    	while( l <= r ) 
    	{
    		int m = (l + r) / 2;
    		
    		if( A[m] > key ) r = m - 1; else l = m + 1;
    	}
    
    	return r + 1;
    }
    
    int query( int p, int l, int r, int nl, int nr )
    {
    	if( nl <= l && nr >= r ) return offset[p] + tree[p];
    
    	int m = (l + r) / 2;
    	int answer = 2000000000;
    
    	if( nl <= m ) answer = min(answer, query(p * 2 + 1, l, m, nl, nr));
    	if (nr > m ) answer = min(answer, query(p * 2 + 2, m + 1, r, nl, nr));
    
    	return answer + offset[p];
    }
    
    void add( int p, int l, int r, int nl, int nr, int value )
    {
    	if( nl <= l && nr >= r ) 
    	{
    		offset[p] += value;
    		return;
    	}
    
    	int m = (l + r) / 2;
    
    	if( nl <= m ) 
    		add( p*2 + 1, l, m, nl, nr, value );
    	if( nr > m ) 
    		add( p*2 + 2, m + 1, r, nl, nr, value );
    	tree[p] = min(offset[p*2 + 1] + tree[p*2 + 1], offset[p*2 + 2] + tree[p*2 + 2]);
    }
    
    void checkOpt( int k )
    {
    	priority_queue<pair<int, int> > heap;
    	int cost = 0;
    
    	for( int i = n - 1; i >= k; --i)
    	{
    		while (!heap.empty() && heap.top().first > D[i])
    		{
    			cost += heap.top().second;
    			heap.pop();
    		}
    		answer = min(answer, opt[i] + cost);
    		heap.push(make_pair(D[i] - S[i], W[i]));
    	}
    }
    
    int main()
    {
    	//freopen( "base.in", "r", stdin );
    	//freopen( "base.out", "w", stdout );
    
    	scanf( "%d %d", &n, &K );
    	for( int i = 1; i < n; ++i ) scanf( "%d", &D[i] );
    	for( int i = 0; i < n; ++i ) scanf( "%d", &C[i] );
    	for( int i = 0; i < n; ++i ) scanf( "%d", &S[i] );
    	for( int i = 0; i < n; ++i ) scanf( "%d", &W[i] );
    
    	answer = 0;
    	for( int i = 0; i < n; ++i ) answer += W[i];
    
    	memset(tree, 0, sizeof(tree));
    	memset(offset, 0, sizeof(offset));
    	for( int i = 0; i < n; ++i ) 
    	{
    		opt[i] = C[i] + query(0, 0, n-1, i, i);
    
    		int x = binarySearch( n, D, D[i]+S[i] );
    		if( x < n ) 
    		{
    //			printf("i = %d, x = %d\n", i, x);
    			add(0, 0, n-1, x, n-1, W[i]);
    		}
    	}
    	checkOpt(0);
    
    //	for (int i = 0; i < n; ++i) printf("%d ", opt[i]);
    //	printf("\n");
    
    	for( int k = 1; k < K; ++k ) 
    	{
    		memset(tree, 0, sizeof(tree));
    		memset(offset, 0, sizeof(offset));
    		for( int i = k - 1; i < n; ++i ) 
    		{
    			add(0, 0, n-1, i, i, opt[i]);
    			events[i].clear();
    		}
    
    		for( int x = k; x < n; ++x )
    		{
    			while (!events[x].empty())
    			{
    				add(0, 0, n-1, 0, events[x].back().first, events[x].back().second);
    				events[x].pop_back();
    			}
    //			printf("k = %d, x = %d, query = %d\n", k, x, query(0, 0, n-1, k-1, x-1));
    			opt[x] = query(0, 0, n-1, k-1, x-1) + C[x];
    
    			int i = binarySearch(n, D, D[x]+S[x]);
    			int j = binarySearch(n, D, D[x]-S[x]); while( j >= 0 && D[j] >= D[x]-S[x] ) --j;
    			if (j >= 0 && i < n) events[i].push_back(make_pair(j, W[x]));
    		}
    		checkOpt(k);
    	}
    	printf( "%d\n", answer );
    
    	return 0;
    }
    
    
    
    • 1

    信息

    ID
    988
    时间
    8000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    4
    已通过
    0
    上传者