zoukankan      html  css  js  c++  java
  • icpc2019 香港 H. Hold the Line (离线+线段树+单调队列)

    题目链接:https://codeforces.com/gym/102452/problem/H

    将所有询问离线下来,按照右端点从小到大排序,每处理一个新询问,就将所有位置小于等于 (r) 的士兵加入线段树,线段树每个节点维护的高度在 ([l,r]) 内的所有节点(位置和插入时间),那么对于当前询问,线段树中所有的点都是小于 (r) 的,我们要找到位置大于 (l) 并且插入时间在该询问之前的节点。

    如果线段树同一个节点上,有士兵位置更靠左((x) 较小)且插入时间更晚,那我们不需要保留该士兵,于是我们维护的就是位置和时间都递增的单调队列,查询是否有合法节点,在该节点的单调队列中二分查找即可。

    时间复杂度 (O(nlogn + mlog^2n))

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 1000010;
    const int INF = 1000000007;
    
    int T;
    int n, m; 
    int tot, b[maxn], ans[maxn];
    
    int c;
    struct CH{
    	int x, h, t; 
    	
    	bool operator < (const CH &y) const{
    		return x < y.x;
    	}
    }cha[maxn];
    
    int q;
    struct Q{
    	int id;
    	int l, r, h, t;
    	bool operator < (const Q &y) const{
    		return r < y.r;
    	}
    }que[maxn];
    
    struct Node{
    	int tail = 0;
    	vector<int> q;
    	vector<int> ti;
    }t[maxn<<2];
    
    void build(int i, int l, int r){
    	t[i].tail = 0; t[i].q.clear();
    	t[i].ti.clear();
    	if(l == r){
    		return;
    	}
    	int mid = (l+r) >> 1;
    	build(i<<1, l, mid); build(i<<1|1, mid+1, r);
    }
    
    void mdf(int i, int p, int lp, int ti, int l, int r){
    	while(t[i].tail > 0 && t[i].ti[t[i].tail-1] > ti) {
    		--t[i].tail;
    	}
    	if(t[i].q.size() == t[i].tail) {
    		t[i].q.push_back(lp);
    		t[i].ti.push_back(ti);	
    		t[i].tail++;
    	} else{	
    		t[i].q[t[i].tail] = lp;
    		t[i].ti[t[i].tail] = ti;
    		t[i].tail++;
    	}
    
    	if(l == r){
    		return;
    	}
    	int mid = (l+r) >> 1;
    	if(p <= mid) mdf(i<<1, p, lp, ti, l, mid);
    	else mdf(i<<1|1, p, lp, ti, mid+1, r);
    }
    
    bool check(int i, int l, int r, int pos, int ti){
    	int L = 0, R = t[i].tail-1;
    	while(L <= R){
    		int mid = (L + R) >> 1;
    		if(t[i].q[mid] >= pos && t[i].ti[mid] <= ti) return true;
    		if(t[i].q[mid] < pos){
    			L = mid + 1; 
    		} else{
    			R = mid - 1;
    		}
    	}
    	return false;
    }
    
    int qry_l(int i, int l, int r, int pos, int ti, int hei){
    	if(l == r){
    		return abs(b[hei]-b[l]);
    	}
    	
    	int mid = (l+r) >> 1;
    	
    	int res = INF;
    	if(hei > mid && check(i<<1|1, mid+1, r, pos, ti)) res = qry_l(i<<1|1, mid+1, r, pos, ti, hei);
    	if(res != INF) return res;
    	if(check(i<<1, l, mid, pos, ti)) res = qry_l(i<<1, l, mid, pos, ti, hei);
    	return res;
    }
    
    int qry_r(int i, int l, int r, int pos, int ti, int hei){
    	if(l == r){
    		return abs(b[hei]-b[l]);
    	}
    	
    	int mid = (l+r) >> 1;
    	
    	int res = INF;
    	if(hei <= mid && check(i<<1, l, mid, pos, ti)) res = qry_r(i<<1, l, mid, pos, ti, hei);
    	if(res != INF) return res;
    	if(check(i<<1|1, mid+1, r, pos, ti)) res = qry_r(i<<1|1, mid+1, r, pos, ti, hei);
    	return res;
    //	if(hei <= mid && check(i<<1, l, mid, pos, ti)) return qry_r(i<<1, l, mid, pos, ti, hei);
    //	else if(check(i<<1|1, mid+1, r, pos, ti)) return qry_r(i<<1|1, mid+1, r, pos, ti, hei);
    //	else return INF;
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	T = read();
    	while(T--){
    		tot = 0, c = 0, q = 0;
    		n = read(), m = read();
    		
    		int op, x, h, l, r;
    		for(int i = 1 ; i <= m ; ++i){
    			op = read();
    			if(op == 0){
    				x = read(), h = read();
    				cha[++c].x = x, cha[c].h = h, cha[c].t = i;
    				b[++tot] = h;
    			} else{
    				l = read(), r = read(), h = read();
    				++q;
    				que[q].id = q, que[q].l = l, que[q].r = r, que[q].h = h, que[q].t = i;
    				b[++tot] = h;
    			}
    		}
    		
    		sort(cha+1, cha+1+c);
    		sort(que+1, que+1+q); 
    		
    		sort(b+1, b+1+tot);
    		tot = unique(b+1, b+1+tot)-b-1;
    		
    		for(int i = 1 ; i <= c ; ++i) cha[i].h = lower_bound(b+1, b+1+tot, cha[i].h) - b;
    		for(int i = 1 ; i <= q ; ++i) que[i].h = lower_bound(b+1, b+1+tot, que[i].h) - b;
    		
    		build(1, 1, tot); // may be tle
    		
    		int cur = 0;
    		for(int i = 1 ; i <= q ; ++i){
    			while(cur < c && cha[cur+1].x <= que[i].r) {
    				mdf(1, cha[cur+1].h, cha[cur+1].x, cha[cur+1].t, 1, tot); //insert the r-th soilder
    				++cur;
    			}
    			
    			if(!check(1, 1, tot, que[i].l, que[i].t)) ans[que[i].id] = -1;
    			else {
    				int res = INF;
    				res = min(res, qry_l(1, 1, tot, que[i].l, que[i].t, que[i].h));
    				res = min(res, qry_r(1, 1, tot, que[i].l, que[i].t, que[i].h));
    				ans[que[i].id] = res; // find the ans
    			}
    		}
    		
    		for(int i = 1 ; i <= q ; ++i) printf("%d
    ", ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    对软件工程的困惑
    团队作业(七)
    团队作业(六)
    团队作业(五)
    团队作业(四)
    团队作业(三)
    团队作业(二)
    团队作业(一)
    代码
    课余作业 采访
  • 原文地址:https://www.cnblogs.com/tuchen/p/15330298.html
Copyright © 2011-2022 走看看