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 500005
using 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]);
else
printf("%lld\n",b[ans[i]]);
}
}