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;
    }
    
  • 相关阅读:
    mac 下安装jenkins
    Appium元素定位难点:tap坐标定位不准确
    Appium元素定位难点:混合式的native+webview
    Linux 上安装 appium
    springMVC之AOP
    设计模式之装饰模式
    设计模式之桥接模式
    MyBatis特殊字符转义
    python+urllib+beautifulSoup实现一个简单的爬虫
    设计模式之代理模式
  • 原文地址:https://www.cnblogs.com/abclzr/p/6359916.html
Copyright © 2011-2022 走看看