bzoj 3110 [Zjoi2013]K大数查询 整体二分

来源:互联网 发布:matlab 数组画图 编辑:程序博客网 时间:2024/05/16 18:11

Description

有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c
如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

Input

第一行N,M
接下来M行,每行形如1 a b c或2 a b c

Output

输出每个询问的结果


       大概是什么加上ZJOI这四个字母都变成刁钻题了吧...

       既然是整体二分题,先考虑如何二分呢,如果根据一般的套路,对于直接对于时间进行二分,我们并不能找到满足二分的性质,但是有二分性质的肯定是一个与时间有关的量,那么就是答案的数值了。

       由于询问的区间固定,那么如果把一部分的数字加进来,答案满足,那么加更多的数字一定满足,所以我们找到了可以二分的特性了。

       那么根据以上特性,在区间[l,r]对于加入操作每次把大于等于mid的数字加进来,对于查询操作看一看查询区间是否能够满足有k个数,如果已经满足了,那么答案[mid,r]这个区间递归得到答案,如果不满足说明答案在[l,mid-1]这个区间,就将当前这个查询的k减去已经构成的答案,再去递归求解即可得到答案。

       由于输入的数值有负数的如果直接进行二分常数略大,所以可以选择先离散化一下即可。

       下附AC代码

#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#define mid ((nl+nr)>>1)#define lson (now<<1)#define rson ((now<<1)|1)#define maxn 500005using namespace std;typedef long long ll;struct nod{ll f,l,r,val,pos,flag;}q[maxn];bool operator<(nod a,nod b){return a.flag==b.flag ? a.pos<b.pos : a.flag<b.flag;}ll sz;ll n,m;ll ans[maxn];ll tot;ll a[maxn],b[maxn];ll id[maxn],temp[maxn];ll sum[maxn<<2],lazy[maxn<<2],flag[maxn<<2];void pushup(ll now){sum[now]=sum[lson]+sum[rson];}void pushdown(ll now,ll nl,ll nr){if(lazy[now]){sum[lson]+=lazy[now]*(mid-nl+1);sum[rson]+=lazy[now]*(nr-mid);lazy[lson]+=lazy[now];lazy[rson]+=lazy[now];lazy[now]=0;}return;}void update(ll ql,ll qr,ll add,ll nl,ll nr,ll now){if(nl>nr || ql>qr) return;if(ql<=nl && nr<=qr){sum[now]+=add*(nr-nl+1);lazy[now]+=add;return;}pushdown(now,nl,nr);if(ql<=mid) update(ql,qr,add,nl,mid,lson);if(mid<qr)  update(ql,qr,add,mid+1,nr,rson);pushup(now);}ll query(ll ql,ll qr,ll nl,ll nr,ll now){if(nl>nr || ql>qr) return 0;if(ql<=nl && nr<=qr){return sum[now];}pushdown(now,nl,nr);ll ans=0;if(ql<=mid) ans+=query(ql,qr,nl,mid,lson);if(mid<qr)  ans+=query(ql,qr,mid+1,nr,rson);pushup(now);return ans;}void dfs(ll nl,ll nr,ll ql,ll qr){if(ql>qr || nl>nr) return;if(nl==nr){for(ll i=ql;i<=qr;i++){ans[q[i].pos]=nl;}return;}ll l1=ql,cnt=0;for(ll i=ql;i<=qr;i++){if(q[i].f==1){if(q[i].val>b[mid]){update(q[i].l,q[i].r,1,1,n,1);q[i].flag=2;}else{cnt++;q[i].flag=1;}}else{ll now=query(q[i].l,q[i].r,1,n,1);if(now>=q[i].val){q[i].flag=2;}else{cnt++;q[i].val-=now;q[i].flag=1;}}}for(ll i=ql;i<=qr;i++){if(q[i].f==1){if(q[i].val>b[mid]){update(q[i].l,q[i].r,-1,1,n,1);}}}sort(q+ql,q+qr+1);dfs(nl,mid,ql,ql+cnt-1);dfs(mid+1,nr,ql+cnt,qr);}int main(){scanf("%lld%lld",&n,&m);for(ll i=1;i<=m;i++){scanf("%lld%lld%lld%lld",&q[i].f,&q[i].l,&q[i].r,&q[i].val);q[i].pos=i;if(q[i].f==1){b[++tot]=q[i].val;}}sort(b+1,b+1+tot);sz=unique(b+1,b+1+tot)-(b+1);memset(ans,-1,sizeof(ans));dfs(1,sz,1,m);for(ll i=1;i<=m;i++)q[i].flag=0;sort(q+1,q+1+m);for(ll i=1;i<=m;i++)if(q[i].f==2){if(ans[i]==-1)printf("%lld\n",ans[i]);elseprintf("%lld\n",b[ans[i]]);}}


       



阅读全文
0 0