1 条题解
-
0
解题思路
考虑对于一个 我们怎么做。
注意到我们可以先把 max 这一维给从小到大排序,然后依次枚举这个 并顷定 为你选取所有 中的最大值,考虑此时如何最优,显然选取 个下标 满足 , 互不相同, 的值最大,发现这东西就是 序列前 个数字中的前 大值,可持久化线段树维护即可。
接下来我们考虑将 从小到大依次做,我们发现给予我们的决策是单调不降的,具体的,若 这个决策劣于 这个决策,则 这个决策将会永远优于 这个决策,于是加上决策单调性优化即可,使用分治来维护,时间复杂度 。
参考代码
ll n; struct node{ ll x,y; }a[200010]; bool cmp(node x,node y){ return x.y<y.y; } ll rt[200010*32],id; ll ls[200010*32],rs[200010*32],k; ll val[200010*32],S[200010*32]; void pushup(ll x){ val[x]=val[ls[x]]+val[rs[x]], S[x]=S[ls[x]]+S[rs[x]]; } void upd(ll pre,ll&x,ll l,ll r,ll y) { if(!x) x=++id; if(l==r) { val[x]=val[pre]+y; S[x]=S[pre]+1; return ; } if(y<=mid) rs[x]=rs[pre], upd(ls[pre],ls[x],l,mid,y); else ls[x]=ls[pre], upd(rs[pre],rs[x],mid+1,r,y); pushup(x); } ll query(ll x,ll l,ll r,ll k) { if(!k) return 0; if(l==r) return k*l; if(S[rs[x]]>=k) return query(rs[x],mid+1,r,k); return val[rs[x]]+query(ls[x],l,mid,k-S[rs[x]]); } ll ans[200010]; void sol(ll l,ll r,ll L,ll R) //[l,r] 决策点为 [L,R] { if(l>r) return ; ll id=-1,l2=max(L,mid); ans[mid]=-9e18; forl(i,l2,R) { ll now=query(rt[i],-1e9,1e9,mid); if(now-a[i].y>ans[mid]) ans[mid]=now-a[i].y, id=i; } sol(l,mid-1,L,id); sol(mid+1,r,id,R); } void _clear(){} void solve() { _clear(); cin>>n; forl(i,1,n) cin>>a[i].x>>a[i].y; sort(a+1,a+1+n,cmp); forl(i,1,n) upd(rt[i-1],rt[i],-1e9,1e9,a[i].x); sol(1,n,1,n); forl(i,1,n) cout<<ans[i]<<endl; }
- 1
信息
- ID
- 1389
- 时间
- 3000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- (无)
- 递交数
- 10
- 已通过
- 2
- 上传者