「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\n", 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\n", res[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/zsbzsb/p/12231701.html

时间: 2024-10-05 13:08:59

「luogu2617」Dynamic Rankings的相关文章

「Luogu P2617」Dynamic Rankings

给出一段序列,每次修改某个数的值和询问区间第 k 小.\((1\le n,m\le 10^5,0\le a_i\le10^9)\) Luogu 分析 动态主席树裸题. 树状数组套主席树,树状数组的每个结点相当于一棵主席树,每次修改操作只在对应树状数组的 logn 个结点所对应的主席树上修改,查询时,将 l - 1 和 r 分别对应的 logn 棵主席树作差即可. 时间复杂度: \(O(n\log^2{n})\) 空间复杂度: \(O(n\log{n})\) 代码 #include <bits/s

BZOJ 1901 Dynamic Rankings

题面: 1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 8088  Solved: 3364[Submit][Status][Discuss] Description 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1 ],a[i+2]--a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]

「随笔」基于当下的思考

马德,说好的技术blog,变成日记本了... 下午的时候莫名其妙的感到很颓废,因为自己的不够强大感到忧虑和危机感十足.现在每每行走在技术的道路上,常觉得如履薄冰,如芒在背. 上大学之前和现在的心态其实差别挺大的,视野的开阔远远不止局限于自己的脚下.不过,这里的「上大学之前」只是一个时间描述词,并不觉得大学是最适合学习的地方,我很失望. 世界上的人无论性别,区域,宗教,兴趣爱好,总可以在互联网上找到志趣相同的人,总是可以不断打破自己的常识与惯性思维.总是有在相同领域比自己更强的人,挺好的. 关于知

「Unity」与iOS、Android平台的整合:3、导出的Android-Studio工程

本文属于「Unity与iOS.Android平台的整合」系列文章之一,转载请注明出处. Unity默认导出的是Android-Eclipse工程,毕竟Eclipse for Android开发在近一两年才开始没落,用户量还是非常巨大的. 个人认为AndroidStudio非常好用,能轻易解决很多Eclipse解决不了或者很难解决的问题. 所以我将Unity导出的Andoid工程分为Eclipse和AndroidStudio两部分. 不过我之后的相关内容都会使用AndroidStudio,希望依然

大数据和「数据挖掘」是何关系?---来自知乎

知乎用户,互联网 244 人赞同 在我读数据挖掘方向研究生的时候:如果要描述数据量非常大,我们用Massive Data(海量数据)如果要描述数据非常多样,我们用Heterogeneous Data(异构数据)如果要描述数据既多样,又量大,我们用Massive Heterogeneous Data(海量异构数据)--如果要申请基金忽悠一笔钱,我们用Big Data(大数据) 编辑于 2014-02-2817 条评论感谢 收藏没有帮助举报作者保留权利 刘知远,NLPer 4 人赞同 我觉得 大数据

开放的智力8:实用「成功学」

可实现的「成功学」 现在我想为这里的年轻人介绍一种可实现的「成功学」.希望这个我自创的理论,可以改变很多人的一生. 当我们评价一个事情值不值得去做.应该花多少精力去做的时候,应该抛弃单一的视角,而是分两个不同的维度来看,一是该事件将给我带来的收益大小(认知.情感.物质.身体方面的收益皆可计入),即「收益值」:二是该收益随时间衰减的速度,我称为「收益半衰期」,半衰期长的事件,对我们的影响会持续得较久较长. 这两个维度正交以后就形成了一个四象限图.我们生活.学习和工作中的所有事情都可以放进这个图里面

1901: Zju2112 Dynamic Rankings

1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 5268  Solved: 2207[Submit][Status][Discuss] Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i

Linux 小知识翻译 - 「syslog」

这次聊聊「syslog」. 上次聊了「日志」(lgo).这次说起syslog,一看到log(日志)就明白是怎么回事了.syslog是获取系统日志的工具. 很多UINIX系的OS都采用了这个程序,它承担了「获取系统全部的日志」这个维持系统正常运行的重要任务. syslog的本体是「syslogd」这个daemon(一般翻译成守护进程),常驻内存中获取日志. syslog的特点是可以通过配置文件「/etc/syslog.conf」,对「哪种应用程序?哪种重要度的信息?记录在哪个文件中?」等进行细致的