蓝桥杯----线段树训练
在来看下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才能将分配的数据清除

浙公网安备 33010602011771号