zoukankan      html  css  js  c++  java
  • BZOJ3600:没有人的算术

    传送门
    如果能给每个 (pair) 按照权值编号就好了
    假设之前已经有了所有的权值的编号,现在考虑编号新的 (pair)
    如果看过了陈立杰的论文的话,不难得到一个重量平衡树的做法
    给树上每个子树一个实数权值区间 ([l,r]),这个点权值为 (mid=frac{l+r}{2})
    左子树 ([l,mid]) 右子树 ([mid,r])
    只需要选择一个树高 (log) 的树(treap/替罪羊树)使得满足精度要求即可

    # include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int maxn(5e5 + 5);
    const double alpha(0.75);
    
    int ls[maxn], rs[maxn], rt, tot, size[maxn], que[maxn], cnt, id[maxn], n, m;
    double val[maxn];
    pair <int, int> info[maxn];
    int mx[maxn << 2];
    
    inline int operator <(pair <int, int> a, pair <int, int> b) {
    	return val[a.first] == val[b.first] ? val[a.second] < val[b.second] : val[a.first] < val[b.first];
    }
    
    void Dfs(int u) {
    	if (!u) return;
    	Dfs(ls[u]), que[++cnt] = u, Dfs(rs[u]);
    }
    
    int Build(int l, int r, double vl, double vr) {
    	if (l > r) return 0;
    	double midv;
    	int mid, o;
    	mid = (l + r) >> 1, o = que[mid], midv = (vl + vr) * 0.5;
    	ls[o] = rs[o] = 0, val[o] = midv;
    	ls[o] = Build(l, mid - 1, vl, midv);
    	rs[o] = Build(mid + 1, r, midv, vr);
    	size[o] = size[ls[o]] + size[rs[o]] + 1;
    	return o;
    }
    
    int Rebuild(int x, double vl, double vr) {
    	cnt = 0, Dfs(x);
    	return Build(1, cnt, vl, vr);
    }
    
    int Insert(int &x, double vl, double vr, pair <int, int> v) {
    	double midv;
    	int ret;
    	midv = (vl + vr) * 0.5;
    	if (!x) {
    		x = ++tot, val[x] = midv, info[x] = v, size[x] = 1;
    		return x;
    	}
    	if (alpha * size[x] < max(size[ls[x]], size[rs[x]])) x = Rebuild(x, vl, vr);
    	if (v == info[x]) return x;
    	else if (v < info[x]) ret = Insert(ls[x], vl, midv, v);
    	else ret = Insert(rs[x], midv, vr, v);
    	size[x] = size[ls[x]] + size[rs[x]] + 1;
    	return ret;
    }
    
    void Modify(int x, int l, int r, int p) {
    	int mid;
    	if (l == r) mx[x] = l;
    	else {
    		mid = (l + r) >> 1;
    		p <= mid ? Modify(x << 1, l, mid, p) : Modify(x << 1 | 1, mid + 1, r, p);
    		mx[x] = val[id[mx[x << 1]]] >= val[id[mx[x << 1 | 1]]] ? mx[x << 1] : mx[x << 1 | 1];
    	}
    }
    
    int Query(int x, int l, int r, int ql, int qr) {
    	int mid, ret, v;
    	if (ql <= l && qr >= r) return mx[x];
    	mid = (l + r) >> 1, ret = -1, v;
    	if (ql <= mid) ret = Query(x << 1, l, mid, ql, qr);
    	if (qr > mid) {
    		v = Query(x << 1 | 1, mid + 1, r, ql, qr);
    		ret = (ret == -1 || val[id[v]] > val[id[ret]]) ? v : ret;
    	}
    	return ret;
    }
    
    int main() {
    	int i, l, r, k;
    	char op;
    	scanf("%d%d", &n, &m);
    	val[0] = -1, Insert(rt, 0, 1, make_pair(0, 0));
    	for (i = 1; i <= n; ++i) Modify(1, 1, n, i);
    	for (i = 1; i <= m; ++i) {
    		scanf(" %c%d%d", &op, &l, &r);
    		if (op == 'C') {
    			scanf("%d", &k);
    			id[k] = Insert(rt, 0, 1, make_pair(id[l], id[r]));
    			Modify(1, 1, n, k);
    		}
    		else printf("%d
    ", Query(1, 1, n, l, r));
    	}
        return 0;
    }
    
  • 相关阅读:
    Java垃圾收集算法
    Java回收方法区中回收的类
    Android 聊天软件客户端
    Android 面试
    基于Android的简单聊天工具-服务器端
    Java多线程
    业务序号重排序
    Dubbo异步转同步
    Dubbo加权轮询负载均衡算法应用之推荐产品
    Linux文件句柄数配置
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/10260000.html
Copyright © 2011-2022 走看看