一道很好的idea題
一開始想過合併 但是總感覺合併的複雜度太大
然後發現其實每個元素被合併次數是可以做到
然後就可以直接暴力插入 複雜度是
用重量平衡樹維護一下
其實不算可持久化 但不想另開一個分類了QaQ
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
char c;
inline void read(int&a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}
struct Node
{
int Optag,anstag,ans,Rnd,Op,no;
Node*lc,*rc;
Node(){lc=rc=NULL;Optag=anstag=ans=Rnd=Op=no=0;}
}*Empty=new Node;
inline void add(Node*a,int Op,int ans)
{a->ans+=ans,a->Op+=Op;a->Optag+=Op,a->anstag+=ans;}
inline void push(Node*a)
{
if(!a->Optag)return;
add(a->lc,a->Optag,a->anstag);
add(a->rc,a->Optag,a->anstag);
a->Optag=a->anstag=0;
}
// l<c r>=c
Node *Split(Node*Root,Node *&l,Node*&r,int c)
{
if(Root==Empty)return l=r=Empty;
Node*L,*R;
push(Root);
if(Root->Op<c)
{
Split(Root->rc,L,R,c);
l=Root;
l->rc=L;
return r=R;
}
else
{
Split(Root->lc,L,R,c);
r=Root;
r->lc=R;
return l=L;
}
}
//a<=b
Node *Merge(Node *a,Node *b)
{
if(a==Empty)return b;
else if(b==Empty)return a;
push(a),push(b);
if(a->Rnd>b->Rnd)return a->rc=Merge(a->rc,b),a;
else return b->lc=Merge(a,b->lc),b;
}
pair<int,int>L[1000001],R[1000001];
Node A[1000001];
int Right(Node*a)
{
if(a==Empty)return -1000;
push(a);
return a->rc!=Empty?Right(a->rc):a->Op;
}
int Left(Node*a)
{
if(a==Empty)return 2000000000;
push(a);
return a->lc!=Empty?Left(a->lc):a->Op;
}
int Ans[1000001];
void Re(Node*a)
{
if(a==Empty)return;
push(a);
Ans[a->no]=a->ans;
Re(a->lc),Re(a->rc);
}
int main()
{
int cnt=0;
int n,m;
read(n);
for(int i=1;i<=n;i++)
{
int u,v;
read(u),read(v);
L[i]=make_pair(-v,u);
}
sort(L+1,L+1+n),read(m);
for(int i=1;i<=m;i++)
{
int u,v;
read(u);
R[i]=make_pair(u,i);
}
sort(R+1,R+1+m);
Node *Root=Empty;
for(int i=1;i<=m;i++)
{
A[i].Rnd=rand()*rand();
A[i].Op=R[i].first;
A[i].lc=A[i].rc=Empty;
A[i].no=R[i].second;
Root=Merge(Root,A+i);
}
for(int i=1;i<=n;i++)
{
int C=L[i].second;
Node *LT,*RT;
Split(Root,LT,RT,C);
if(LT==Empty)
{
add(Root=RT,-C,1);
continue;
}
if(RT==Empty){Root=LT;continue;}
add(RT,-C,1);
int l=Right(LT),r=Left(RT);
while(l>r)
{
Node *LL,*LR,*RL,*RR;
Split(LT,LL,LR,r+1);
Split(RT,RL,RR,r+1);
RT=RR;
LT=Merge(Merge(LL,RL),LR);
l=Right(LT);
r=Left(RT);
}
Root=Merge(LT,RT);
}
Re(Root);
for(int i=1;i<=m;i++)
printf("%d ",Ans[i]);
return 0;
}