題面c++
英文題面git
題意:數據結構
題解:考慮枚舉每一個物品,用數據結構來維護人。先將物品按\(v_i\)遞減排序,用平衡樹來維護人。設當前枚舉到了物品\(i\),那麼全部平衡樹內權值大於等於\(v_i\)的節點的權值都要減去\(v_i\),而後答案\(+1\),但這樣會破壞平衡樹的二叉搜索樹的性質。ui
考慮權值在\([v_i+1,2v_i]\)的節點會破壞性質,咱們就將這些點刪除,而後一個一個暴力插回平衡樹裏。因爲這些點的權值都至少減半,每一個點只會被這樣操做\(log_B\)次。因此複雜度是正確的。spa
建議使用fhq-treap。注意最後求答案時要將打的標記所有下傳。code
時間複雜度:\(O(nlogm+mlogmlogB)\)。blog
代碼:排序
#include<bits/stdc++.h> using namespace std; #define re register int #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) typedef long long ll; #define I inline void #define IN inline int #define C(x,y) memset(x,y,sizeof(x)) #define STS system("pause") template<class D>I read(D &res){ res=0;register D g=1;register char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } mt19937 _rnd(time(0)); struct P{ int c,w; friend bool operator < (P x,P y){ return x.w==y.w?x.c<y.c:x.w>y.w; } }p[202000]; int n,m,a[202000],sa[202000],rk[202000],ans[202000]; int root,ch[202000][2],siz[202000],rnd[202000],laz[202000],tag[202000]; inline bool bbb(int x,int y){return a[x]<a[y];} I push_up(int x){ siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1; } I build(int &k,int l,int r){ if(l>r)return; k=(l+r)>>1;siz[k]=1;rnd[k]=_rnd(); build(ch[k][0],l,k-1);build(ch[k][1],k+1,r); push_up(k); } I add(int k,int val,int num){ laz[k]+=val;a[k]-=val;ans[k]+=num;tag[k]+=num; } I push_down(int x){ if(ch[x][0])add(ch[x][0],laz[x],tag[x]); if(ch[x][1])add(ch[x][1],laz[x],tag[x]); laz[x]=tag[x]=0; } I split(int now,int k,int &x,int &y){ if(!now)return x=y=0,void(); if(laz[now])push_down(now); if(a[now]<=k){ x=now;split(ch[x][1],k,ch[x][1],y);push_up(x); } else{ y=now;split(ch[y][0],k,x,ch[y][0]);push_up(y); } } IN merge(int x,int y){ if(!x||!y)return x+y; if(laz[x])push_down(x);if(laz[y])push_down(y); if(rnd[x]<rnd[y]){ ch[x][1]=merge(ch[x][1],y);push_up(x);return x; } else{ ch[y][0]=merge(x,ch[y][0]);push_up(y);return y; } } I damage(int x){ if(laz[x])push_down(x); if(ch[x][0])damage(ch[x][0]); if(ch[x][1])damage(ch[x][1]); ch[x][0]=ch[x][1]=0;siz[x]=1;rnd[x]=_rnd(); re X,Y;split(root,a[x]-1,X,Y); root=merge(merge(X,x),Y); } I getans(int x){ if(laz[x])push_down(x); if(ch[x][0])getans(ch[x][0]); if(ch[x][1])getans(ch[x][1]); } int main(){ read(m); F(i,1,m)read(p[i].c),read(p[i].w);sort(p+1,p+1+m); read(n);F(i,1,n)read(a[i]),sa[i]=i; sort(sa+1,sa+1+n,bbb);F(i,1,n)rk[sa[i]]=i; sort(a+1,a+1+n);build(root,1,n); re X,Y,Z; F(i,1,m){ split(root,p[i].c-1,X,Y);add(Y,p[i].c,1);split(Y,p[i].c,Y,Z);root=merge(X,Z); damage(Y); } getans(root); F(i,1,n)printf("%d ",ans[rk[i]]); return 0; } /* 3 7 5 3 5 4 3 2 13 14 2 100 500 50 499 4 50 200 150 100 */