zoukankan      html  css  js  c++  java
  • 【APIO2018】新家

    题目链接

    【APIO2018】新家

    做法

    对于这种区间修改、单点询问的题目,可以将询问离线再扫描线。
    考虑对于一个答案 $ ans_i $ 合法,当且仅当 $ (l_i + ans_i, INF) $ 中每种店上一次出现的位置不小于 $ l_i + ans_i $ 。对于每种店都开一个 multiset 即可维护前驱。
    这样每一次加入/删除会需要区间修改前驱,代码难度大,考虑 $ (l_i + ans_i, INF) $ 中每种店上一次出现的位置不小于 $ l_i + ans_i $ 的另一种解释,即 $ (l_i + ans_i, INF) $ 每个位置中每种店每个位置上一次出现的位置最小值不小于 $ l_i + ans_i $ ,然后就可以单点修改了。用线段树维护前驱最小值。
    询问可以二分答案,更优秀的做法是在线段树上二分。

    #include <bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef multiset<int>::iterator IT;
    const int N = 600010, LG = 20, INF = 1000000000;
    int n, k, m, ans[N], clr;
    struct Q {
    	int opt, pos, type, pri;
    	Q(int Opt = 0, int Pos = 0, int Type = 0, int Pri = 0) :
    		opt(Opt), pos(Pos), type(Type), pri(Pri) {}
    	inline bool operator<(const Q &yy)const {
    		return pri == yy.pri ? opt < yy.opt : pri < yy.pri;
    	}
    }; Q q[N + N]; int len;
    
    multiset<int> pp[N], st[N * LG];
    int rt, tot, cnt, lf[N * LG], rf[N * LG], mn[N * LG], id[N * LG];
    
    inline int Max(const int &x, const int &y) { return x > y ? x : y; }
    inline int Min(const int &x, const int &y) { return x < y ? x : y; }
    void mdy(int &u, int l, int r, int x, int ad, int dl) {
    	if(!u) u = ++tot;
    	if(l >= r) {
    		if(!id[u]) id[u] = ++cnt;
    		multiset<int> &s = st[id[u]];
    		if(ad) s.insert(ad);
    		if(dl) s.erase(s.find(dl));
    		mn[u] = s.size() ? *s.begin() : INF; return ;
    	}
    	int mid = (l + r) >> 1;
    	if(x <= mid) mdy(lf[u], l, mid, x, ad, dl);
    	else mdy(rf[u], mid + 1, r, x, ad, dl);
    	mn[u] = Min(mn[lf[u]], mn[rf[u]]);
    }
    void add(Q x) {
    	multiset<int> &s = pp[x.type];
    	IT itr = s.upper_bound(x.pos), itl = itr; --itl;
    	mdy(rt, 0, INF, *itr, x.pos, *itl), mdy(rt, 0, INF, x.pos, *itl, 0);
    	s.insert(x.pos); if(s.size() == 3) ++clr;
    }
    void del(Q x) {
    	multiset<int> &s = pp[x.type]; s.erase(s.find(x.pos));
    	IT itr = s.upper_bound(x.pos), itl = itr; --itl;
    	mdy(rt, 0, INF, *itr, *itl, x.pos), mdy(rt, 0, INF, x.pos, 0, *itl);
    	if(s.size() == 2) --clr;
    }
    int ask(Q x) {
    	if(clr < k) return -1;
    	int l = 0, r = INF, mid, t, tt = INF, u = rt;
    	for(; l < r;) {
    		mid = (l + r) >> 1, t = Min(tt, mn[rf[u]]);
    		if(x.pos <= mid && t + mid >= x.pos * 2)
    			tt = t, r = mid, u = lf[u];
    		else u = rf[u], l = mid + 1;
    	}
    	return l - x.pos;
    }
    int main() {
    	scanf("%d%d%d", &n, &k, &m), mn[0] = INF;
    	for(int i = 1; i <= k; i++)
    		pp[i].insert(-INF), pp[i].insert(INF), mdy(rt, 0, INF, INF, -INF, 0);
    	for(int i = 1, x, t, a, b; i <= n; i++) {
    		scanf("%d%d%d%d", &x, &t, &a, &b);
    		q[++len] = Q(1, x, t, a), q[++len] = Q(2, x, t, b + 1);
    	}
    	for(int i = 1, x, y; i <= m; i++)
    		scanf("%d%d", &x, &y), q[++len] = Q(3, x, i, y);
    	sort(q + 1, q + len + 1);
    	for(int i = 1; i <= len; i++) {
    		if(q[i].opt == 1) add(q[i]);
    		else if(q[i].opt == 2) del(q[i]);
    		else ans[q[i].type] = ask(q[i]);
    	}
    	for(int i = 1; i <= m; i++) printf("%d
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Jersey 2.x 运行项目
    Jersey 2.x 探索新建的工程
    Jersey 2.x 从Maven Archetype 创建一个新项目
    Jersey 2.x 服务器端应用支持的容器
    Jersey 2.x JDK 上的客户端应用
    Jersey 2.x 基于 Servlet 的服务器端应用
    =面试题:java面试基本方向 背1 有用 项目二技术学完再看
    面试题:项目开发经验总结 框架 比较难的问题 可以找一下有用
    面试题: !=!=未看
    面试题:大公司面试题 !=!=未看
  • 原文地址:https://www.cnblogs.com/daniel14311531/p/10904742.html
Copyright © 2011-2022 走看看