Dynamic Rankings (tree-like array set weights segment tree)

Dynamic Rankings (tree-like array set weights segment tree)

Given a sequence of n numbers a[1], a[2], a[3]...a[n], the program must answer the query: for a given i,j,k, in a[ i], a[i+1], a[i+2]... What is the k-th smallest number in a[j] (1≤k≤j-i+1), and you can change some a[ After the value of i] is changed, the program can continue to answer the above questions for the changed a. You need to write a program that reads the sequence a from the input file, and then reads in a series of instructions, including query instructions and modification instructions.

For each query command, you must output the correct answer. There are two positive integers n (1≤n≤10000), m (1≤m≤10000). Represent the length of the sequence and the number of instructions, respectively.

This problem is the k-th largest problem with the repair interval. It can be done by cdq divide and conquer, or it can be done by tree nesting. Due to the modification, if the violence is modified on the chairman tree, the time complexity will explode, which is \(O(nlogn)\) . Looking at the query again, it is \(O(logn)\) , which inspires us to average the two of them, so a tree array is used. A weight segment tree is built on each interval of the tree-like array to maintain the number of occurrences of each value in this interval. Then modifying the value of a certain number will affect logn intervals on the tree array, and then the single-point modification time of the weight line segment tree is \(O(logn)\) , and the total time is \(O(logn^2n)\ ) of . To query the kth largest value of the interval \([l, r]\) , you need to get the weighted segment tree of \([1, l-1]\) and \([1, r]\) , and then compare them to Subtraction will still affect logn intervals. Since the query time of the weighted segment tree interval is \(O(logn)\) , the total time is also \(O(logn^2n)\) . Pay attention to discretization, this question is still quite difficult to write.

Therefore, the data structure can balance the time complexity of the operation.

#include <cctype>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=2e4+5;
int n, m, a[maxn], b[maxn], cntb, rt[maxn];
int c1[maxn], c2[maxn], c3[maxn];
int size[maxn*400], cseg, ls[maxn*400], rs[maxn*400];
int tset1[maxn], tset2[maxn], cnt1, cnt2;
inline int lowbit(int x){ return x&(-x); } //树状数组上的权值线段树

void ins(int &now, int l, int r, int pos, int v){
    if (!now) now=++cseg; size[now]+=v;
    if (l==r) return; int mid=(l+r)>>1;
    if (pos<=mid) ins(ls[now], l, mid, pos, v);
    else ins(rs[now], mid+1, r, pos, v);
}

void add(int x, int v){
    int k=lower_bound(b+1, b+cntb+1, a[x])-b;
    for (int i=x; i<=n; i+=lowbit(i))
        ins(rt[i], 1, cntb, k, v);
}

int query(int l, int r, int v){  //logn个权值线段树一起跳
    if (l==r) return l;
    int sum=0, mid=(l+r)>>1;
    for (int i=1; i<=cnt1; ++i) sum-=size[ls[tset1[i]]];
    for (int i=1; i<=cnt2; ++i) sum+=size[ls[tset2[i]]];
    if (v<=sum){
        for (int i=1; i<=cnt1; ++i) tset1[i]=ls[tset1[i]];
        for (int i=1; i<=cnt2; ++i) tset2[i]=ls[tset2[i]];
        return query(l, mid, v);
    } else {
        for (int i=1; i<=cnt1; ++i) tset1[i]=rs[tset1[i]];
        for (int i=1; i<=cnt2; ++i) tset2[i]=rs[tset2[i]];
        return query(mid+1, r, v-sum);
    }
}

inline void get(int &x){
    char c; int flag=1;
    for (; !isdigit(c=getchar()); ) if (c=='-') flag=-1;
    for (x=c-48; c=getchar(), isdigit(c); )
        x=(x<<3)+(x<<1)+c-48;
    if (flag==-1) x=-x;
}

int main(){
    get(n); get(m); char c;
    for (int i=1; i<=n; ++i) get(a[i]), b[++cntb]=a[i];
    for (int i=0; i<m; ++i){
        while (!isgraph(c=getchar()));
        get(c1[i]); get(c2[i]);
        if (c=='Q') get(c3[i]); else b[++cntb]=c2[i];
    }
    sort(b+1, b+cntb+1); cntb=unique(b+1, b+cntb+1)-b-1;
    for (int i=1; i<=n; ++i) add(i, 1);
    for (int i=0; i<m; ++i) if (c3[i]){
        cnt1=cnt2=0;  //把要查询的区间都标出来
        for (int j=c1[i]-1; j; j-=lowbit(j)) tset1[++cnt1]=rt[j];
        for (int j=c2[i]; j; j-=lowbit(j)) tset2[++cnt2]=rt[j];
        printf("%d\n", b[query(1, cntb, c3[i])]);
    } else { add(c1[i], -1); a[c1[i]]=c2[i]; add(c1[i], 1); }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325288375&siteId=291194637