蓝桥杯----线段树训练

在来看下multiset的使用:

  我们知道multiset是默认从小到大排序,那么如果我们想从大到小排序应该如何办?

  

    greater<int>是用来指定从大到小排序的

 

《线段树----维护区间第k大》

好博客<-----

 由于这个第k大的k比较小,而且只有单点修改,那么我们可以用线段树

树中的每一个节点都维护着一个8个大小的数组

这个数组是保存前8大的值

 

#include<iostream>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
const int N=1e5+5;
struct tree{
    int l,r,arr[9];
}tr[N<<4];
int L,n; 
void pushup(int id)
{
    int i=1,j=1;
    int *a=tr[id<<1].arr,*b=tr[id<<1|1].arr;
    int *c=tr[id].arr,cnt=1;
    while (i<=8 && j<=8 && cnt<=8)
    {
        if (a[i]>=b[j])
            c[cnt++]=a[i++];
        else c[cnt++]=b[j++];
    }
    while (i<=8 && cnt<=8)
        c[cnt++]=a[i++];
    while (j<=8 && cnt<=8)
        c[cnt++]=b[j++];
} 
void build(int id,int l,int r)
{
    tr[id].l=l,tr[id].r=r;
    for (int i=1;i<=8;i++)
        tr[id].arr[i]=0;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(id<<1,l,mid),build(id<<1|1,mid+1,r);
}
void modify(int id,int pos,int w)
{
    if (tr[id].l==tr[id].r)
    {
        tr[id].arr[1]=w;
        return ;
    }
    int mid=(tr[id].l+tr[id].r)>>1;
    if (pos<=mid)
        modify(id<<1,pos,w);
    else modify(id<<1|1,pos,w);
    pushup(id);
    /*cout<<id<<" change: "; 
    for (int i=1;i<=8;i++)
        cout<<tr[id].arr[i]<<" ";
    cout<<endl;*/
}
int *query(int id,int l,int r)
{
    if (tr[id].l>=l && tr[id].r<=r)
        return tr[id].arr;
    int mid=(tr[id].l+tr[id].r)>>1;
    if (l>mid)
        return query(id<<1|1,l,r);
    else if (r<=mid)
        return query(id<<1,l,r);
    else 
    {
        int *a=query(id<<1,l,r),*b=query(id<<1|1,l,r);
        int i=1,j=1;
        int *c=new int [9],cnt=1;
        while (i<=8 && j<=8 && cnt<=8)
        {
            if (a[i]>=b[j])
                c[cnt++]=a[i++];
            else c[cnt++]=b[j++];
        }
        while (i<=8 && cnt<=8)
            c[cnt++]=a[i++];
        while (j<=8 && cnt<=8)
            c[cnt++]=b[j++];
        return c;
    }
}
int main()
{
    cin>>L>>n;
    build(1,1,L);
    while (n--)
    {
        char op;
        int a,b;
        cin>>op>>a>>b;
        if (op=='C')
            modify(1,a,b);
        else 
            cout<<query(1,a,b)[8]<<endl;
    }
    return 0;    
} 

 

 

 

 注意在query函数中的一段代码:

 一定要写成Int *c=new int [9] , 而不能写成int c[9]

如果写成int c[9]那么就是在函数栈上分配空间,一旦函数结束

那么栈上的数据都会被pop

即如果return 了这个c,那么很有可能指向的是错误的数据或非法访问

 

但是如果写成int *c=new int [9]

那么就是在堆上分配空间,只要用特定的API才能将分配的数据清除

 

posted @ 2023-06-07 17:22  次林梦叶  阅读(29)  评论(0)    收藏  举报