P8701 [蓝桥杯 2019 国 B] 第八大奇迹 题解
显然可以直接将维护的值变为区间前 $8$ 大,为实现的简洁,可使用 vector,使用归并合并信息达到 $\mathcal{8n\log n}$。由于偷懒,归并部分我直接写的 sort,加上 vector 的大常数,加 O2 后即可通过。
时间复杂度:$\mathcal{O}(8n\log n)$。
代码:
#include <bits/stdc++.h>
using namespace std;
#define pb emplace_back
const int N=1e5+10;
int n,m;
vector<int> tr[N<<2];
vector<int> operator+(vector<int> a,vector<int> b){
vector<int> c=a;
for(int i:b)c.pb(i);
return c;
}
void pushup(int u){
tr[u]=tr[u<<1]+tr[u<<1|1];
sort(tr[u].begin(),tr[u].end(),greater<int>());
while(tr[u].size()>8)tr[u].pop_back();
}
void update(int u,int l,int r,int k,int val){
if(l==r){
tr[u].clear();tr[u].pb(val);
return;
}
int mid=(l+r)>>1;
if(k<=mid)update(u<<1,l,mid,k,val);
else update(u<<1|1,mid+1,r,k,val);
pushup(u);
}
vector<int> query(int u,int l,int r,int L,int R){
if(L<=l&&r<=R)return tr[u];
int mid=(l+r)>>1;
vector<int> vec;
if(L<=mid)vec=vec+query(u<<1,l,mid,L,R);
if(mid<R)vec=vec+query(u<<1|1,mid+1,r,L,R);
sort(vec.begin(),vec.end(),greater<int>());
while(vec.size()>8)vec.pop_back();
return vec;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
char opt;int x,y;
cin>>opt>>x>>y;
if(opt=='C')update(1,1,n,x,y);
else{
vector<int> tmp=query(1,1,n,x,y);
if(tmp.size()==8)cout<<tmp.back()<<"\n";
else cout<<0<<"\n";
}
}
return 0;
}