一开始有n个非负整数hi,接下来会进行m次操作,第i次操作给出一个数c[i],要求你选出c[i]个大于零的数并将它们减去1。
问最多可以进行多少轮操作后无法操作(即没有c[i]个大于零的数)
暴力显然,就是每次找出前c[i]大的那些数,把他们都-1 (S),
那么这个就用Splay来维护即可,
但显然,不用Splay,直接用一棵线段树,不过在处理前段相同的数的时候要特判一下,
复杂度: O(nlog(n))
#include
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
#define SD(q) ((q)==b[b[q].fa].r)
using namespace std;
const int N=1000500,INF=2147483640;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
int a[N];
int root,b0;
struct qqww
{
int l,r,fa,si;
int cha,nm;
int v,ans;
}b[N*3];
void merge(int q)
{
b[q].si=b[b[q].l].si+1+b[b[q].r].si;
b[q].ans=b[b[q].l].ans+b[q].v+b[b[q].r].ans;
b[q].nm=b[b[q].l].nm+b[q].cha+b[b[q].r].nm;
}
void rotate(int q)
{
int w=b[q].fa;
if(SD(q))
{
b[w].r=b[q].l;
b[b[q].l].fa=w;
b[q].l=w;
}else
{
b[w].l=b[q].r;
b[b[q].r].fa=w;
b[q].r=w;
}
if(SD(w))b[b[w].fa].r=q;
else b[b[w].fa].l=q;
b[q].fa=b[w].fa;
b[w].fa=q;
merge(w);
merge(q);
}
void Splay(int q,int T)
{
for(;b[q].fa!=T;)
{
if(b[b[q].fa].fa!=T)
{
if(SD(q)==SD(b[q].fa))rotate(b[q].fa);
else rotate(q);
}
rotate(q);
}
if(!T)root=q;
}
int BHn,hos,nm;
int findT(int q,int si)
{
if(b[b[q].r].ans>=si)
{
nm+=b[b[q].l].nm+b[q].cha;
BHn+=b[b[q].l].si+1;
return findT(b[q].r,si);
}
hos=si-b[b[q].r].ans;
si-=b[b[q].r].ans+b[q].v;
if(si<1)
{
BHn+=b[b[q].l].si+1;
nm+=b[b[q].l].nm+b[q].cha;
return q;
}
return findT(b[q].l,si);
}
int findS(int q,int si)
{
if(b[b[q].l].si>=si)return findS(b[q].l,si);
si-=b[b[q].l].si+1;
if(si<1)return q;
return findS(b[q].r,si);
}
int findnm(int q,int si)
{
if(b[b[q].l].nm+b[q].cha>si&&b[q].l)return findnm(b[q].l,si);
si-=b[b[q].l].nm+b[q].cha;
if(si<1)return q;
return findnm(b[q].r,si);
}
void DLT(int q)
{
Splay(findS(root,q-1),0);
if(b[b[root].r].si<2)
{
b[b[root].r].fa=0;
b[root].r=0;
merge(root);
return;
}
Splay(q=findS(root,q+1),root);
b[b[q].l].fa=0;
b[q].l=0;
merge(q),merge(root);
}
void ADD1(int q,int w)
{
if(!w)return;
Splay(findnm(root,q),0);
if(b[b[root].l].nm+b[root].cha==q)
{
b[root].v+=w;
}else
{
b0++;
b[b0].fa=root;
b[b0].l=b[root].l;
b[b[root].l].fa=b0;
b[root].l=b0;
b[b0].cha=q-b[b[b0].l].nm;
b[root].cha-=b[b0].cha;
b[b0].v=w;
merge(b[b0].l);
merge(b0);
}
merge(root);
}
void Jian(int q,int w)
{
if(!w)return;
Splay(q,0);
b[q].v-=w;
merge(root);
}
int main()
{
freopen("sequence.in","r",stdin);
freopen("sequence.out","w",stdout);
int q,w,_;
read(n),read(_);
fo(i,1,n)read(a[i]);
sort(a+1,a+1+n);
b[b0=1].v=1e9;
q=0;
fo(i,1,n)if(a[i]!=a[i+1])
{
b0++;
b[b0].fa=b0-1,b[b0-1].r=b0;
b[b0].v=i-q;b[b0].cha=a[i]-a[q];
q=i;
}
b[b0].r=b0+1;
b[b0+1].fa=b0;
b[b0+1].cha=1e9;merge(b0+1);
b0++;
fod(i,b0,1)merge(i);
Splay(b0/2,0);
root=b0/2;
bool BR=0;
fo(I,1,_)
{
read(w);
BHn=nm=hos=0;
q=findT(root,w);
if(q<2){BR=1;printf("%d\n",I-1);break;}
if(b[q].cha==1)
{
DLT(BHn);
ADD1(nm,b[q].v-hos);
ADD1(nm-1,hos);
}else
{
Splay(q,0);
b[q].cha--;
merge(q);
int t=b[q].v;
Jian(q,b[q].v-hos);
ADD1(nm,t-hos);
}
}
if(!BR)printf("%d\n",_);
return 0;
}