1. 程式人生 > >bzoj3110 [Zjoi2013]K大數查詢

bzoj3110 [Zjoi2013]K大數查詢

題目描述

題解:

看不懂樣例的dalao看這裡:

每個位置加入一個數c指的是插入,一個位置上可以有很多數

整體二分。

將修改和詢問放在一起,然後二分值域,每次有詢問時判斷$k$和$sum[l,r]$的大小。

最後保證$[l,l]$時$k$減成$0$即可。

程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 50050
#define ll long long
inline ll rd()
{
    ll f=1,c=0
;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} return f*c; } ll n,m,cnt; ll ans[N],to[N]; struct str { ll opt,a,b,id; ll c; }p[N],tmpl[N],tmpr[N]; ll tot; struct Pair { ll x;ll id; Pair(){} Pair(ll x,ll i):x(x),id(i){} }pr[N];
bool cmp(Pair a,Pair b) { return a.x<b.x; } struct segtree { ll siz[N<<2],vl[N<<2],tag[N<<2]; bool rec[N<<2]; void add(ll u,ll d) { tag[u]+=d; vl[u]+=siz[u]*d; } void rece(ll u) { rec[u]=1; vl[u]=tag[u]=0; }
void update(ll u) { vl[u] = vl[u<<1]+vl[u<<1|1]; } void build(ll l,ll r,ll u) { siz[u] = r-l+1; if(l==r)return ; ll mid = (l+r)>>1; build(l,mid,u<<1); build(mid+1,r,u<<1|1); } void init() { build(1,n,1); } void pushdown(ll u) { if(rec[u]) { rece(u<<1); rece(u<<1|1); rec[u]=0; } if(tag[u]) { add(u<<1,tag[u]); add(u<<1|1,tag[u]); tag[u]=0; } } void insert(ll l,ll r,ll u,ll ql,ll qr,ll d) { if(l==ql&&r==qr) { add(u,d); return ; } pushdown(u); ll mid = (l+r)>>1; if(qr<=mid)insert(l,mid,u<<1,ql,qr,d); else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d); else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d); update(u); } ll query(ll l,ll r,ll u,ll ql,ll qr) { if(l==ql&&r==qr)return vl[u]; pushdown(u); ll mid = (l+r)>>1; if(qr<=mid)return query(l,mid,u<<1,ql,qr); else if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr); else return query(l,mid,u<<1,ql,mid)+query(mid+1,r,u<<1|1,mid+1,qr); } }tr; void divi(ll l,ll r,ll beg,ll ens) { if(beg>ens)return ; if(l==r) { for(ll i=beg;i<=ens;i++) ans[p[i].id] = to[l]; return ; } ll mid = (l+r)>>1; ll lt = 0,rt = 0; tr.rece(1); bool l1=0,r1=0; for(ll i=beg;i<=ens;i++) { if(p[i].opt==1) { if(p[i].c<=mid) { tmpl[++lt] = p[i]; }else { tr.insert(1,n,1,p[i].a,p[i].b,1); tmpr[++rt] = p[i]; } }else { ll now = tr.query(1,n,1,p[i].a,p[i].b); if(now<p[i].c) { p[i].c-=now; tmpl[++lt] = p[i]; l1=1; }else { tmpr[++rt] = p[i]; r1=1; } } } for(ll i=beg;i<=beg+lt-1;i++)p[i]=tmpl[i-beg+1]; for(ll i=beg+lt;i<=ens;i++)p[i]=tmpr[i-beg-lt+1]; if(l1)divi(l,mid,beg,beg+lt-1); if(r1)divi(mid+1,r,beg+lt,ens); } int main() { // freopen("tt.in","r",stdin); // freopen("tt.out","w",stdout); n = rd(),m = rd(); for(ll i=1;i<=m;i++) { p[i].opt = rd(),p[i].a = rd(),p[i].b = rd(),p[i].c = rd(); if(p[i].opt==2) { p[i].id = ++cnt; }else { pr[++tot] = Pair(p[i].c,i); } } sort(pr+1,pr+1+tot,cmp); ll las = 100005;ll k = 0; for(ll i=1;i<=tot;i++) { if(las!=pr[i].x) { las = pr[i].x; k++;to[k]=las; } p[pr[i].id].c = k; } tr.init(); divi(1,k,1,m); for(ll i=1;i<=cnt;i++) printf("%lld\n",ans[i]); return 0; }