zoukankan      html  css  js  c++  java
  • 【BZOJ 1901】【ZJU 2112】Dynamic Rankings

    http://www.lydsy.com/JudgeOnline/problem.php?id=1901
    重新用整体二分写了一下。
    整体二分的思想详见论文。
    貌似带修区间k大和静态区间k大都是(O(nlog^2n))
    cdq是对时间分治,整体二分是对答案分治。
    对于动态区间k大怎么实现我还想了很长时间呢,感觉模板题都想这么长时间。。。
    动态区间k大的关键步骤是把修改变成两个操作,删除和插入。
    这样在一个分治函数内部就可以扫时间轴然后在特定权值范围内的删除和插入分别在bits上-1和+1。
    相比较在线bits套主席树,离线整体二分跑得飞快。
    离散化后跑得能快一点,不离散的话时间复杂度就是(O(nlog nlog 10^9)),离散的话时间复杂度是(O(nlog^2n))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 10003;
    
    struct node {int x, y, k, op, id;} B[N << 2], q1[N << 2], q2[N << 2];
    int tot = 0, a[N], n, m, bits[N << 1], top = 0, H[N << 1], cnt = 0;
    int ans[N], id[N << 2], anstot = 0, que[N << 1], q1len, q2len;
    
    void add(int x, int flag) {for (; x <= n; x += (x & (-x))) bits[x] += flag;}
    int sum(int x) {int ret = 0; for (; x; x -= (x & (-x))) ret += bits[x]; return ret;}
    
    void solve(int p, int q, int l, int r) {
    	if (p > q) return;
    	if (l == r) {
    		for (int i = p; i <= q; ++i)
    			if (B[i].op == 3)
    				ans[B[i].id] = l;
    		return;
    	}
    	
    	int mid = (l + r) >> 1;
    	for (int i = p; i <= q; ++i) {
    		if (B[i].op != 3) {
    			if (B[i].y <= mid)
    				add(B[i].x, B[i].op);
    		}
    		else que[i] = sum(B[i].y) - sum(B[i].x - 1);
    	}
    	
    	for (int i = p; i <= q; ++i)
    		if (B[i].op != 3 && B[i].y <= mid) add(B[i].x, -B[i].op);
    	
    	q1len = q2len = 0;
    	for (int i = p; i <= q; ++i)
    		if (B[i].op != 3) {
    			if (B[i].y > mid) q2[++q2len] = B[i];
    			else q1[++q1len] = B[i];
    		} else {
    			if (que[i] >= B[i].k) q1[++q1len] = B[i];
    			else B[i].k -= que[i], q2[++q2len] = B[i];
    		}
    	
    	int tmp = p - 1;
    	for (int i = 1; i <= q1len; ++i)
    		B[++tmp] = q1[i];
    	for (int i = 1; i <= q2len; ++i)
    		B[++tmp] = q2[i];
    	
    	tmp = p + q1len - 1;
    	solve(p, tmp, l, mid);
    	solve(tmp + 1, q, mid + 1, r);
    }
    
    int main() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d", a + i);
    		B[++tot] = (node) {i, a[i], 0, 1, 0};
    		H[++cnt] = a[i];
    	}
    	
    	int x, y, k;
    	char c[2];
    	for (int i = 1; i <= m; ++i) {
    		scanf("%s", c);
    		if (c[0] == 'Q') {
    			scanf("%d%d%d", &x, &y, &k);
    			B[++tot] = (node) {x, y, k, 3, ++anstot};
    		} else {
    			scanf("%d%d", &x, &y);
    			B[++tot] = (node) {x, a[x], 0, -1, 0};
    			B[++tot] = (node) {x, y, 0, 1, 0};
    			H[++cnt] = (a[x] = y);
    		}
    	}
    	
    	stable_sort(H + 1, H + cnt + 1);
    	cnt = unique(H + 1, H + cnt + 1) - H;
    	for (int i = 1; i <= tot; ++i)
    		if (B[i].op != 3)
    			B[i].y = lower_bound(H + 1, H + cnt, B[i].y) - H;
    	
    	solve(1, tot, 1, cnt - 1);
    	
    	for (int i = 1; i <= anstot; ++i) printf("%d
    ", H[ans[i]]);
    	return 0;
    }
    
  • 相关阅读:
    java多线程之系列目录
    RecyclerView的源码分析
    ConCurrentHashMap在1.7和1.8区别
    插件化之细节
    组件化之开发细节
    组件化之开发总结
    线程之volatile基本内容
    线程之Synchronized基本内容
    设计模式之动态代理模式原理介绍
    操作系统之内存映射
  • 原文地址:https://www.cnblogs.com/abclzr/p/6359916.html
Copyright © 2011-2022 走看看