整体二分模板,所谓整体二分其实就是将修改与询问保存下来,然后二分值域;
树套树亦可,但是码量较大;
#include <iostream> #include <cstdio> #include <algorithm> using namespace std;const int N=1e5+7;typedef long long ll; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘) f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } struct Query { int o,l,r,k,i; Query(int o=0,int l=0,int r=0,int k=0,int i=0) {this->o=o;this->l=l;this->r=r;this->k=k;this->i=i;} }q[N<<2],q1[N<<2],q2[N<<2];int n,m,c[N],w[N],res[N]; inline int lowbit(int x){return x&(-x);} inline void add(int x,int y){for(int i=x;i<=n;i+=lowbit(i))c[i]+=y;} inline int sum(int x){int res=0;while(x)res+=c[x],x-=lowbit(x);return res;} inline void solve(int s,int t,int l,int r) { if(l==r) { for(int i=s;i<=t;i++) if(q[i].o==2)res[q[i].i]=l; return; }int mid=(l+r)>>1,cnt1=0,cnt2=0; for(int i=s;i<=t;i++) { if(q[i].o==1) { if(q[i].l<=mid) add(q[i].i,q[i].r),q1[++cnt1]=q[i]; else q2[++cnt2]=q[i]; } else { int x=sum(q[i].r)-sum(q[i].l-1); if(x>=q[i].k) q1[++cnt1]=q[i]; else q[i].k-=x,q2[++cnt2]=q[i]; } } for(int i=1;i<=cnt1;i++) if(q1[i].o==1)add(q1[i].i,-q1[i].r); for(int i=1;i<=cnt1;i++) q[s+i-1]=q1[i]; for(int i=1;i<=cnt2;i++) q[s+cnt1+i-1]=q2[i]; if(cnt1) solve(s,s+cnt1-1,l,mid); if(cnt2) solve(s+cnt1,t,mid+1,r); } int main() { n=read(),m=read();int cnt=0,tot=0; for(int i=1;i<=n;i++) q[++cnt]=Query(1,w[i]=read(),1,0,i); for(int i=1;i<=m;i++) { char ch;cin>>ch; if(ch==‘Q‘) q[++cnt].o=2,q[cnt].l=read(),q[cnt].r=read(),q[cnt].k=read(),q[cnt].i=++tot; else { int l=read(),r=read(); q[++cnt]=Query(1,w[l],-1,0,l); q[++cnt]=Query(1,w[l]=r,1,0,l); } }solve(1,cnt,0,1e9+1); for(int i=1;i<=tot;i++) cout<<res[i]<<endl; return 0; }
原文地址:https://www.cnblogs.com/chtomede/p/12082942.html
时间: 2024-10-09 15:07:15