一个板子题.不过看评论那么多O(n^2)的解法...反正我用O(n^2)试了试..没过...
其实二分套线段树还挺常见的.
不过因为长时间没写过题了..我线段树板子都快忘了,花了一个多小时才回忆起来...
下面是思路:
由于是将所有>=x的数减一.所以我们很容易想到线段树的区间修改和区间查询.
但是值修改之后我们如何确定第一个>=x的位置呢?
通过二分,首先将数组排序,因为修改的限制,所以数组只会是一个不减的数组.
那么我们就可以二分位置,确定一个位置pos是第一个>=x的位置,
然后如果这个位置>n,就说明没有一个元素符合条件.
否则输出n-l+1.然后更新线段树即可.
还是比较好想的,注意一下线段树的实现(退役选手4个月不刷题流下了菜鸡的眼泪QAQ)
当然,这个题目可能有更好的方法,但我限于智商和水平,只有这个一般解法了QAQ.
ACCode:
#include<stdlib.h> #include<string.h> #include<stdio.h> #include<time.h> #include<math.h> // srand((unsigned)time(NULL));rand(); #include<map>//unordered_map #include<set>//multiset #include<deque> #include<queue> #include<stack> #include<bitset> #include<string> #include<fstream> #include<iostream> #include<algorithm> #define ll long long #define PII pair<int,int> #define PLL pair<ll,ll> #define clean(a,b) memset(a,b,sizeof(a)) using namespace std; const int MAXN=2e5+10; //const int MAXM=10; const int INF32=0x3f3f3f3f; const ll INF64=0x3f3f3f3f3f3f3f3f; const ll MOD=1e9+7; const double PI=acos(-1.0); const double EPS=1.0e-8; //unsigned register // ios::sync_with_stdio(false) class SegTree{ struct Node{ int sum; int l,r,len; int lazy; }; Node T[MAXN<<2]; void PushUp(int rt){ T[rt].sum=T[rt<<1].sum+T[rt<<1|1].sum; } void PushDown(int rt){ if(T[rt].lazy!=0){ T[rt<<1].lazy+=T[rt].lazy; T[rt<<1|1].lazy+=T[rt].lazy; T[rt<<1].sum+=T[rt<<1].len*T[rt].lazy; T[rt<<1|1].sum+=T[rt<<1|1].len*T[rt].lazy; T[rt].lazy=0; } } public: void Build(int l,int r,int rt,int A[]){ T[rt].l=l;T[rt].r=r;T[rt].len=r-l+1; T[rt].lazy=0; if(l==r){ T[rt].sum=A[l]; return ; }int mid=(l+r)>>1; Build(l,mid,rt<<1,A);Build(mid+1,r,rt<<1|1,A); PushUp(rt); } int Query(int x,int rt){ if(T[rt].l==T[rt].r) return T[rt].sum; PushDown(rt); if(T[rt<<1].r>=x) return Query(x,rt<<1); else return Query(x,rt<<1|1); } void Update(int ql,int qr,int x,int rt){ // printf("l=%d r=%d ql=%d qr=%d\n",T[rt].l,T[rt].r,ql,qr); if(ql<=T[rt].l&&qr>=T[rt].r){ T[rt].lazy+=x; T[rt].sum+=T[rt].len*x; return ; }PushDown(rt); if(qr<=T[rt<<1].r) Update(ql,qr,x,rt<<1); else if(ql>=T[rt<<1|1].l) Update(ql,qr,x,rt<<1|1); else{ Update(ql,qr,x,rt<<1);Update(ql,qr,x,rt<<1|1); } } void Show(int rt){ printf("l=%d r=%d T[rt].sum=%d\n",T[rt].l,T[rt].r,T[rt].sum); if(T[rt].l==T[rt].r) return ; PushDown(rt); Show(rt<<1);Show(rt<<1|1); } }; int A[MAXN]; SegTree st; int main(){ int n,q;scanf("%d%d",&n,&q); int mx=0; for(int i=1;i<=n;++i){ int x;scanf("%d",&A[i]); mx=max(mx,x); }sort(A+1,A+1+n);st.Build(1,n,1,A); while(q--){ int x;scanf("%d",&x); int l=1,r=n,mid; while(l<=r){ mid=(l+r)>>1; int xx=st.Query(mid,1); // printf("xx=%d x=%d\n",xx,x); if(st.Query(mid,1)<x) l=mid+1; else r=mid-1; } // printf("l=%d\n",l); if(l>n) printf("0\n"); else{ printf("%d\n",n-l+1); st.Update(l,n,-1,1); }//st.Show(1); } }