题目:
题目描述
给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作。
1. ai(1≤i≤n)变成 x(0≤x≤109)。
2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1≤k≤r-l+1)小。
输入格式
第一行包含两个数 n(1≤n≤2×104)和 m(1≤m≤2×104),表示序列长度和操作次数。
接下来一行 n 个数,以空格隔开,表示 a1,a2,…,an 。
接下来m行,每行为以下两种格式之一:
- 0 i x , 表示 ai=x。
- 1 l r k ,求 al,al+1,…,ar 的第 k 小。
输出格式
对于每次询问,输出单独的一行表示答案。
样例数据 1
题解:
待修改的权值线段树的模板题
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std; int getint() { int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } const int N=2e4+5,M=2e6+5; struct node { int op,x,y,k; }q[N]; struct tree { int lc,rc,size; }tr[M]; int n,m,len,tot,a[N],b[N<<1],bit[N],pos[N]; void dic_init() { sort(b+1,b+len+1); len=unique(b+1,b+len+1)-b-1; for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+len+1,a[i])-b; for(int i=1;i<=m;i++) if(!q[i].op) q[i].y=lower_bound(b+1,b+len+1,q[i].y)-b; } void Insert(int &k,int l,int r,int x) { if(!k)k=++tot; tr[k].size++; if(l==r)return; int mid=l+r>>1; if(x<=mid)Insert(tr[k].lc,l,mid,x); else Insert(tr[k].rc,mid+1,r,x); } void Add(int x) { for(int i=x;i<=n;i+=i&(-i)) Insert(bit[i],1,len,a[x]); } void Delete(int k,int l,int r,int x) { tr[k].size--; if(l==r)return; int mid=l+r>>1; if(x<=mid)Delete(tr[k].lc,l,mid,x); else Delete(tr[k].rc,mid+1,r,x); } void Rec(int x) { for(int i=x;i<=n;i+=i&(-i)) Delete(bit[i],1,len,a[x]); } void pre(int x,int y) { for(int i=x;i>0;i-=i&(-i)) pos[i]=bit[i]; for(int i=y;i>0;i-=i&(-i)) pos[i]=bit[i]; } int calc(int x,int y) { int res=0; for(int i=x;i>0;i-=i&(-i)) res+=tr[tr[pos[i]].lc].size; for(int i=y;i>0;i-=i&(-i)) res-=tr[tr[pos[i]].lc].size; return res; } void trans(int x,int y,int f) { for(int i=x;i>0;i-=i&(-i)) if(!f)pos[i]=tr[pos[i]].lc; else pos[i]=tr[pos[i]].rc; for(int i=y;i>0;i-=i&(-i)) if(!f)pos[i]=tr[pos[i]].lc; else pos[i]=tr[pos[i]].rc; } int query(int rt1,int rt2,int l,int r,int k) { if(l==r)return l; int delta=calc(rt1,rt2); int mid=l+r>>1; if(delta>=k) { trans(rt1,rt2,0); return query(rt1,rt2,l,mid,k); } else { trans(rt1,rt2,1); return query(rt1,rt2,mid+1,r,k-delta); } } int main() { //freopen("a.in","r",stdin); n=getint(),m=getint(); for(int i=1;i<=n;i++) a[i]=getint(),b[++len]=a[i]; for(int i=1;i<=m;i++) { q[i].op=getint(); q[i].x=getint(); q[i].y=getint(); if(!q[i].op)b[++len]=q[i].y; else q[i].k=getint(); } dic_init(); for(int i=1;i<=n;i++)Add(i); for(int i=1;i<=m;i++) if(!q[i].op) { Rec(q[i].x); a[q[i].x]=q[i].y; Add(q[i].x); } else { pre(q[i].y,q[i].x-1); cout<<b[query(q[i].y,q[i].x-1,1,len,q[i].k)]<<' '; } return 0; }