P2617 Dynamic Rankings (动态开点权值线段树 + 树状数组)

题意:带修求区间k小

题解:回忆在使用主席树求区间k小时 利用前缀和的思想 既然是前缀和 那么我们可以使用更擅长维护前缀和的树状数组

   但是这里每一颗权值线段树就不是带版本的 而是维护数组里i号点的权值信息 所以实际上并不是主席树 每一棵和前面一棵并没有共用结点

   对于一次修改操作 我们先删去这个点的原信息 再更新进去 树状数组上的点一起跳 可能看代码比较好理解一点

   这个方法限制性也很强 必须离线

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 2;

int n, m, len, cnt;
int a[100005];
int b[200005];
int sum[MAXN * 400];
int ls[MAXN * 400];
int rs[MAXN * 400];
int t[MAXN];
int temp[2][50];
int tot1, tot0;

struct node {
    char opt;
    int u, v, w;
}E[100005];

void add(int &o, int l, int r, int k, int v) {
    if(!o) o = ++cnt;
    sum[o] += v;
    int mid = l + r >> 1;
    if(l == r) return;

    if(k <= mid) add(ls[o], l, mid, k, v);
    else add(rs[o], mid + 1, r, k, v);
}

void update(int x, int pos, int v) {
    for(int i = x; i <= n; i += (i & -i)) add(t[i], 1, len, pos, v);
}

void prepare_query(int l, int r) {
    tot1 = tot0 = 0;
    for(int i = r; i >= 1; i -= (i & -i)) temp[1][++tot1] = t[i];
    for(int i = l; i >= 1; i -= (i & -i)) temp[0][++tot0] = t[i];
}

int query(int l, int r, int k) {
    if(l == r) return l;

    int mid = l + r >> 1;
    int res = 0;
    for(int i = 1; i <= tot1; i++) res += sum[ls[temp[1][i]]];
    for(int i = 1; i <= tot0; i++) res -= sum[ls[temp[0][i]]];
    if(res >= k) {
        for(int i = 1; i <= tot1; i++) temp[1][i] = ls[temp[1][i]];
        for(int i = 1; i <= tot0; i++) temp[0][i] = ls[temp[0][i]];
        return query(l, mid, k);
    } else {
        for(int i = 1; i <= tot1; i++) temp[1][i] = rs[temp[1][i]];
        for(int i = 1; i <= tot0; i++) temp[0][i] = rs[temp[0][i]];
        return query(mid + 1, r, k - res);
    }
}

char s[5];
int main() {
    cnt = 0;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
    len = n;

    for(int i = 1; i <= m; i++) {
        scanf("%s", s);
        E[i].opt = s[0];
        if(E[i].opt == ‘Q‘) scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w);
        else {
            scanf("%d%d", &E[i].u, &E[i].v);
            b[++len] = E[i].v;
        }
    }
    sort(b + 1, b + 1 + len);
    len = unique(b + 1, b + 1 + len) - b - 1;

    for(int i = 1; i <= n; i++) {
        int tt = lower_bound(b + 1, b + 1 + len, a[i]) - b;
        update(i, tt, 1);
    }

    for(int i = 1; i <= m; i++) {
        if(E[i].opt == ‘Q‘) {
            prepare_query(E[i].u - 1, E[i].v);
            printf("%d\n", b[query(1, len, E[i].w)]);
        } else {
            int t1 = lower_bound(b + 1, b + 1 + len, a[E[i].u]) - b;
            update(E[i].u, t1, -1);
            a[E[i].u] = E[i].v;
            int t2 = lower_bound(b + 1, b + 1 + len, a[E[i].u]) - b;
            update(E[i].u, t2, 1);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/lwqq3/p/11315693.html

时间: 2024-07-28 21:47:00

P2617 Dynamic Rankings (动态开点权值线段树 + 树状数组)的相关文章

【bzoj4605】崂山白花蛇草水 权值线段树套KD-tree

题目描述 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob特地为他准备了999,999,999,999,999,999瓶崂山白花蛇草水,想要灌神犇Aleph.神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bob最终答应了他的请求,但蒟蒻Bob决定将计就计,也让神犇Aleph回答一些问题.具体说来,蒟蒻Bob会在一个宽敞的广场上

【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结点的权值线段树之间毫无关联 可以看这个:http://blog.csdn.net/popoqqq/article/details/40108669?utm_source=tuicool #include<cstdio> #include<algorithm> using namespa

动态求区间K大值(权值线段树)

我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和前一颗树没有关系,so,并不需要可持久化,一个朴素的权值线段树就可以啦. 我们知道普通的线段树是刚开始就把所有的节点都开了,但我们发现并不需要,因为每个点里的操作并不是很多,很大一部分的节点是用不到的,那么我们就可以不开.用Ls 和 Rs 来记左右儿子的地址,随用随开即可. #include<bit

B20J_2733_[HNOI2012]永无乡_权值线段树合并

Description:n座岛,编号从1到n,每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用1到 n来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛.现在有两种操作:B x y表示在岛 x与岛y之间修建一座新桥.Q x k表示询问当前与岛 x连通的所有岛中第k重要的是哪座岛,即所有与岛 x连通的岛中重要度排名第 k小的岛是哪座,请你输出那个岛的编号. 对于100%的数据n≤100000,m≤n,q≤300000. 分析:读懂题后发现是一道线段树合并的裸题.

权值线段树&amp;&amp;线段树合并

权值线段树 所谓权值线段树,就是一种维护值而非下标的线段树,我个人倾向于称呼它为值域线段树. 举个栗子:对于一个给定的数组,普通线段树可以维护某个子数组中数的和,而权值线段树可以维护某个区间内数组元素出现的次数. 在实现上,由于值域范围通常较大,权值线段树会采用离散化或动态开点的策略优化空间. 更新操作: 更新的时候,我们向线段树中插入一个值v,那么所有包含v的区间值都需要+1.(每个节点维护对应区间中出现了多少个数) int update (long long v,long long l,lo

[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]

Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为Pi.同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同.调度系统会经常向 查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个 )的优先级之和是多少.特别的,如

【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree

[BZOJ4605]崂山白花蛇草水 Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob特地为他准备了999,999,999,999,999,999瓶崂山白花蛇草水,想要灌神犇Aleph.神犇Aleph求(跪着的)蒟蒻Bob不要灌他,由于神犇Aleph是神犇,蒟蒻Bob最终答应了他的请求,但蒟蒻Bob决定将计就计,也让神犇Aleph回答

【bzoj2161】布娃娃 权值线段树

题目描述 小时候的雨荨非常听话,是父母眼中的好孩子.在学校是老师的左右手,同学的好榜样.后来她成为艾利斯顿第二代考神,这和小时候培养的良好素质是分不开的.雨荨的妈妈也为有这么一个懂事的女儿感到高兴.一次期末考试,雨荨不知道第多少次,再次考了全年级第一名.雨荨的妈妈看到女儿100分的成绩单时,脸上又泛起了幸福的笑容,作为奖励,她给雨荨买了n个布娃娃.细心的雨荨发现,第i个布娃娃有一个耐心值P[i]以及一个魅力值C[i],并且还有能够忍受的耐心值的上限R[i]以及下限L[i].当一个布娃娃j满足L[

【BZOJ-2892&amp;1171】强袭作战&amp;大sz的游戏 权值线段树+单调队列+标记永久化+DP

2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] Description 在一个没有冬马的世界里,经历了学园祭后的春希着急着想要见到心爱的雪菜.然而在排队想见雪菜的fans太多了,春希一时半会凑不到雪菜面前. 作为高帅富,这样的问题怎么能难倒春希?春希从武也手中拿到了取自金闪闪宝库里的多啦A梦的传话筒,并且给每一个排队的fans都发了一个传话筒. 于