如题,下述代码中需要完全遍历线段树,估测时间复杂度为 O(nmlogm) ,但实际得分 95 ,且除 #18 其它点最多只有 132 ms ,请求解答分析实际时间复杂度。
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
constexpr ll N=200005,INF=2e9+7;
struct prt {
ll s,t,id;
bool operator<(const prt&b)const {
return t<b.t;
}
} p[N];
ll n,m;
vector<ll> ans[N];
struct sta {
ll fl,v,p;
};
sta merge(const sta&a,const sta&b) {
sta res;
if(a.v<=b.v) res=sta({0,a.v,a.p});
else res=sta({0,b.v,b.p});
res.fl=a.fl&&b.fl;
return res;
}
struct node {
ll l,r,tS;
sta s;
} tr[N*4];
void build(ll x,ll l,ll r) {
tr[x]=node({l,r,0,sta({1,0,l})});
if(l==r) return;
ll mid=(l+r)>>1;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
tr[x].s=merge(tr[x*2].s,tr[x*2+1].s);
}
void msub(ll x,ll v) {
if(tr[x].s.fl==1) return;
if(tr[x].s.v>=v) {
tr[x].s.v-=v;
tr[x].tS+=v;
return;
}
if(tr[x].l==tr[x].r) {
tr[x].s=sta({0,max(tr[x].s.v-v,0ll),tr[x].l});
if(tr[x].s.v==0) tr[x].s.fl=1;
return;
}
msub(x*2,v+tr[x].tS);
msub(x*2+1,v+tr[x].tS);
tr[x].tS=0;
tr[x].s=merge(tr[x*2].s,tr[x*2+1].s);
}
void madd(ll x,ll p,ll v) {
if(tr[x].l==tr[x].r) {
tr[x].s.v+=v;
tr[x].s.fl=0;
return;
}
if(tr[x].tS!=0) {
msub(x*2,tr[x].tS);
msub(x*2+1,tr[x].tS);
tr[x].tS=0;
}
if(p<=tr[x*2].r) madd(x*2,p,v);
else madd(x*2+1,p,v);
tr[x].s=merge(tr[x*2].s,tr[x*2+1].s);
}
sta qpos(ll x,ll l,ll r) {
if(l>tr[x].r||tr[x].l>r) return sta({0,INF,N+1});
if(l<=tr[x].l&&tr[x].r<=r) return tr[x].s;
if(tr[x].tS!=0) {
msub(x*2,tr[x].tS);
msub(x*2+1,tr[x].tS);
tr[x].tS=0;
}
return merge(qpos(x*2,l,r),qpos(x*2+1,l,r));
}
ll read() {
ll x=0,f=1;
char ch=0;
while(ch<'0'||ch>'9') {
ch=getchar();
if(ch=='-') f=-1;
}
while(ch>='0'&&ch<='9') {
x=x*10+(ch-'0');
ch=getchar();
}
return x*f;
}
void write(ll x) {
static ll S[35];
ll top=0;
do {
S[top++]=x%10;
x/=10;
} while(x);
if(!top) putchar('0');
while(top) putchar(S[--top]+'0');
}
int main() {
n=read();
m=read();
for(ll i=1; i<=n; ++i) {
p[i].s=read();
p[i].t=read();
p[i].id=i;
}
sort(p+1,p+1+n);
build(1,1,m);
for(ll i=1,pr=0; i<=n; ++i) {
msub(1,p[i].t-pr);
pr=p[i].t;
ll pos=qpos(1,1,m).p;
ans[pos].push_back(p[i].id);
madd(1,pos,p[i].s);
}
for(ll i=1; i<=m; ++i) {
sort(ans[i].begin(),ans[i].end());
write(ans[i].size());
for(ll x:ans[i]) {
putchar(' ');
write(x);
}
putchar('\n');
}
return 0;
}