zoukankan      html  css  js  c++  java
  • 【题解】Berland.Taxi Codeforces 883L 模拟 线段树 堆

    Prelude

    题目传送门:ヾ(•ω•`)o


    Solution

    按照题意模拟即可。
    维护一个优先队列,里面装的是正在运营中的出租车,关键字是乘客的下车时间。
    维护一个线段树,第(i)个位置表示第(i)个房子前面有没有停放出租车,这样在有人需要打车的时候可以快速找到离她最近的车的位置。
    对每个房子维护一个堆,里面装的是停在这个房子前面的出租车,关键字是出租车的编号和上一个乘客下车的时间,上一个乘客下车越早,等待时间越长。
    然后模拟时间的流逝就可以了,代码非常好写。


    Code

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <queue>
    #include <utility>
    #include <cstdlib>
    #include <cassert>
    
    using namespace std;
    typedef long long ll;
    const int MAXN = 200010;
    const int INF = 0x3f3f3f3f;
    int _w;
    
    int n, k, m, x[MAXN], a[MAXN], b[MAXN];
    ll t[MAXN];
    
    namespace SGT {
    	int sumv[MAXN<<2], ql, qr, qv;
    	void _add( int o, int L, int R ) {
    		sumv[o] += qv;
    		if( L == R ) return;
    		int M = (L+R)/2, lc = o<<1, rc = lc|1;
    		if( ql <= M ) _add(lc, L, M);
    		else _add(rc, M+1, R);
    	}
    	void add( int p, int v ) {
    		ql = p, qv = v;
    		_add(1, 1, n);
    	}
    	void _queryl( int o, int L, int R ) {
    		if( L >= ql && R <= qr ) {
    			if( !sumv[o] ) return;
    			while( L != R ) {
    				int M = (L+R)/2, lc = o<<1, rc = lc|1;
    				if( sumv[lc] ) o = lc, R = M;
    				else o = rc, L = M+1;
    			}
    			qv = L;
    		} else {
    			int M = (L+R)/2, lc = o<<1, rc = lc|1;
    			if( ql <= M && !qv ) _queryl(lc, L, M);
    			if( qr > M && !qv ) _queryl(rc, M+1, R);
    		}
    	}
    	int queryl( int l, int r ) {
    		ql = l, qr = r, qv = 0;
    		_queryl(1, 1, n);
    		return qv;
    	}
    	void _queryr( int o, int L, int R ) {
    		if( L >= ql && R <= qr ) {
    			if( !sumv[o] ) return;
    			while( L < R ) {
    				int M = (L+R)/2, lc = o<<1, rc = lc|1;
    				if( sumv[rc] ) o = rc, L = M+1;
    				else o = lc, R = M;
    			}
    			qv = L;
    		} else {
    			int M = (L+R)/2, lc = o<<1, rc = lc|1;
    			if( qr > M && !qv ) _queryr(rc, M+1, R);
    			if( ql <= M && !qv ) _queryr(lc, L, M);
    		}
    	}
    	int queryr( int l, int r ) {
    		ql = l, qr = r, qv = 0;
    		_queryr(1, 1, n);
    		return qv;
    	}
    }
    
    struct Node {
    	ll t;
    	int id;
    	Node() {}
    	Node( ll t, int id ):
    		t(t), id(id) {}
    	bool operator<( const Node &rhs ) const {
    		return t == rhs.t ? id > rhs.id : t > rhs.t;
    	}
    };
    priority_queue<Node> pq[MAXN], evt;
    
    void prelude() {
    	for( int i = 1; i <= k; ++i ) {
    		pq[x[i]].push( Node(0, i) );
    		SGT::add(x[i], 1);
    	}
    }
    
    void run( ll t ) {
    	while( !evt.empty() && evt.top().t <= t ) {
    		Node car = evt.top(); evt.pop();
    		SGT::add(x[car.id], 1);
    		// printf( "car.id = %d, x[id] = %d
    ", car.id, x[car.id] );
    		pq[x[car.id]].push(car);
    	}
    }
    int use( int pos ) {
    	Node car = pq[pos].top(); pq[pos].pop();
    	SGT::add(pos, -1);
    	return car.id;
    }
    int freecar( int pos ) {
    	if( !SGT::sumv[1] ) return 0;
    	int left = SGT::queryr(1, pos);
    	int right = SGT::queryl(pos, n);
    	// printf( "left = %d, right = %d
    ", left, right );
    	if( !left ) left = -INF;
    	if( !right ) right = INF;
    	if( left == right ) {
    		return use(left);
    	} else if( pos-left < right-pos ) {
    		return use(left);
    	} else if( right-pos < pos-left ) {
    		return use(right);
    	} else {
    		Node cl = pq[left].top(), cr = pq[right].top();
    		if( cl.t == cr.t ) {
    			if( cl.id < cr.id ) {
    				return use(left);
    			} else {
    				return use(right);
    			}
    		} else if( cl.t < cr.t ) {
    			return use(left);
    		} else {
    			return use(right);
    		}
    	}
    }
    void solve() {
    	ll now = 0;
    	for( int i = 0; i < m; ++i ) {
    		now = max(now, t[i]);
    		run(now);
    		int car = freecar( a[i] );
    		// printf( "now = %lld, car = %d
    ", now, car );
    		if( !car ) {
    			now = max(now, evt.top().t);
    			run(now);
    			// printf( "now = %lld, car = %d
    ", now, car );
    			car = freecar( a[i] );
    		}
    		// printf( "now = %lld, car = %d
    ", now, car );
    		printf( "%d %lld
    ", car, now - t[i] + abs(x[car] - a[i]) );
    		evt.push( Node(now + abs(x[car] - a[i]) + abs(a[i] - b[i]), car) );
    		x[car] = b[i];
    	}
    }
    
    int main() {
    	_w = scanf( "%d%d%d", &n, &k, &m );
    	for( int i = 1; i <= k; ++i )
    		_w = scanf( "%d", x+i );
    	for( int i = 0; i < m; ++i )
    		_w = scanf( "%lld%d%d", t+i, a+i, b+i );
    	prelude(), solve();
    	return 0;
    }
    
  • 相关阅读:
    TCPUDPSocket调试工具v2.2
    C#高性能Socket服务器IOCP实现
    c#使用HttpListener监听HTTP请求
    Winform Socket通信
    C# 方法中的this参数(扩展方法)
    C# 两种方法实现HTTP协议迷你服务器
    C#访问HTTP请求
    Socket通信原理
    C#数据decimal保留两位小数
    单机网站架构云化后架构图
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/7900621.html
Copyright © 2011-2022 走看看