• 「luogu2617」Dynamic Rankings


    「luogu2617」Dynamic Rankings

    传送门
    树套树直接上树状数组套主席树,常数很大就是了。
    树套树参考代码:

    /*--------------------------------
      Code name: DynamicRanking.cpp
      Author: The Ace Bee
      This code is made by The Ace Bee
    --------------------------------*/
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define rg register
    using namespace std;
    const int MAXN = 500010;
    inline int lowbit(int x) { return x & -x; }
    inline int read() {
    	int s = 0; bool f = false; char c = getchar();
    	while (c < '0' || c > '9') f |= (c == '-'), c = getchar();
    	while (c >= '0' && c <= '9') s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
    	return f ? -s : s;
    }
    int n, m, a[MAXN], len, b[MAXN], rt[MAXN];
    int tot, num[MAXN << 5], lc[MAXN << 5], rc[MAXN << 5];
    int cnt[2], tmp[2][20];
    struct node{ bool f; int l, r, k; int pos, key; }p[MAXN];
    inline void update(int& p, int l, int r, int x, int v) {
    	if (!p) p = ++tot;
    	num[p] += v;
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	if (x <= mid) update(lc[p], l, mid, x, v);
    	else update(rc[p], mid + 1, r, x, v);
    }
    inline void HJTupdate(int x, int v) {
    	int k = lower_bound(b + 1, b + len + 1, a[x]) - b;
    	for (rg int i = x; i <= n; i += lowbit(i)) update(rt[i], 1, len, k, v);
    }
    inline int query(int l, int r, int k) {
    	if (l == r) return l;
    	int mid = (l + r) >> 1, sum = 0;
    	for (rg int i = 1; i <= cnt[1]; ++i) sum += num[lc[tmp[1][i]]];
    	for (rg int i = 1; i <= cnt[0]; ++i) sum -= num[lc[tmp[0][i]]];
    	if (k <= sum) {
    		for (rg int i = 1; i <= cnt[1]; ++i) tmp[1][i] = lc[tmp[1][i]];
    		for (rg int i = 1; i <= cnt[0]; ++i) tmp[0][i] = lc[tmp[0][i]];
    		return query(l, mid, k);
    	} else {
    		for (rg int i = 1; i <= cnt[1]; ++i) tmp[1][i] = rc[tmp[1][i]];
    		for (rg int i = 1; i <= cnt[0]; ++i) tmp[0][i] = rc[tmp[0][i]];
    		return query(mid + 1, r, k - sum);
    	}
    }
    inline int HJTquery(int l, int r, int k) {
    	memset(tmp, 0, sizeof tmp), cnt[0] = cnt[1] = 0;
    	for (rg int i = r; i; i -= lowbit(i)) tmp[1][++cnt[1]] = rt[i];
    	for (rg int i = l; i; i -= lowbit(i)) tmp[0][++cnt[0]] = rt[i];
    	return query(1, len, k);
    }
    int main() {
    	n = read(), m = read();
    	for (rg int i = 1; i <= n; ++i) a[i] = read(), b[++len] = a[i];
    	for (rg int i = 1; i <= m; ++i) {
    		char s[5]; scanf("%s", s);
    		p[i].f = (s[0] == 'Q');
    		if (p[i].f)
    			p[i].l = read(), p[i].r = read(), p[i].k = read();
    		else
    			p[i].pos = read(), p[i].key = read(), b[++len] = p[i].key;
    	}
    	sort(b + 1, b + len + 1);
    	len = unique(b + 1, b + len + 1) - b - 1;
    	for (rg int i = 1; i <= n; ++i) HJTupdate(i, 1);
    	for (rg int i = 1; i <= m; ++i) {
    		if (p[i].f)
    			printf("%d
    ", b[HJTquery(p[i].l - 1, p[i].r, p[i].k)]);
    		else {
    			HJTupdate(p[i].pos, -1);
    			a[p[i].pos] = p[i].key;
    			HJTupdate(p[i].pos, 1);
    		}
    	}
    	return 0;
    }
    

    整体二分的话就把修改看做减去开始的再加上后来的,跑得比树套树快远了~
    整体二分参考代码:

    #include <algorithm>
    #include <cstdio>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    using namespace std;
    template < class T > inline void read(T& s) {
    	s = 0; int f = 0; char c = getchar();
    	while ('0' > c || c > '9') f |= c == '-', c = getchar();
    	while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    	s = f ? -s : s;
    }
    
    const int _ = 2e5 + 5, INF = 1e9;
    
    int n, m, q, a[_], tr[_], res[_];
    int num; struct node { int opt, id, l, r, k; } t[_ << 1], tt1[_ << 1], tt2[_ << 1];
    
    inline void update(int x, int v) { for (rg int i = x; i <= n; i += i & -i) tr[i] += v; }
    
    inline int query(int x) { int res = 0; for (rg int i = x; i >= 1; i -= i & -i) res += tr[i]; return res; }
    
    inline void solve(int ql, int qr, int l, int r) {
    	if (ql > qr || l > r) return ;
    	if (l == r) { for (rg int i = ql; i <= qr; ++i) if (t[i].opt == 1) res[t[i].id] = l; return ; }
    	int mid = (l + r) >> 1, p1 = 0, p2 = 0;
    	for (rg int i = ql; i <= qr; ++i) {
    		if (t[i].opt == 0) {
    			if (t[i].l <= mid) update(t[i].r, t[i].k), tt1[++p1] = t[i]; else tt2[++p2] = t[i];
    		} else {
    			int cnt = query(t[i].r) - query(t[i].l - 1);
    			if (cnt >= t[i].k) tt1[++p1] = t[i]; else t[i].k -= cnt, tt2[++p2] = t[i];
    		}
    	}
    	for (rg int i = 1; i <= p1; ++i) if (tt1[i].opt == 0) update(tt1[i].r, -tt1[i].k);
    	for (rg int i = 1; i <= p1; ++i) t[ql + i - 1] = tt1[i];
    	for (rg int i = 1; i <= p2; ++i) t[ql + p1 + i - 1] = tt2[i];
    	solve(ql, ql + p1 - 1, l, mid), solve(ql + p1, qr, mid + 1, r);
    }
    
    int main() {
    	read(n), read(m);
    	for (rg int i = 1; i <= n; ++i) read(a[i]), t[++num] = (node) { 0, 0, a[i], i, 1 };
    	char s[5];
    	for (rg int l, r, k, i = 1; i <= m; ++i) {
    		scanf("%s", s);
    		if (s[0] == 'Q') read(l), read(r), read(k), t[++num] = (node) { 1, ++q, l, r, k };
    		else read(l), read(r), t[++num] = (node) { 0, 0, a[l], l, -1 }, t[++num] = (node) { 0, 0, a[l] = r, l, 1 };
    	}
    	solve(1, num, -INF, INF);
    	for (rg int i = 1; i <= q; ++i) printf("%d
    ", res[i]);
    	return 0;
    }
    
  • 相关阅读:
    【转帖】如何学好 C 语言
    设计模式:单件模式(Singleton Pattern)
    如果软件正在占领全世界.为什么程序员得不到任何尊重?
    【转】程序员技术练级攻略
    JS闭包理解的彻底吗?
    设计模式:原型模式(Prototype Pattern)
    关于基础类型
    IIS5和IIS6的Asp.net应用程序生命周期事件和Global.asax文件
    App_Code文件夹和Bin文件夹
    构造函数
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12231701.html
Copyright © 2020-2023  润新知