题解:P12718 [Algo Beat Contest 002 E] Excellent Game
思路
首先我们猜一个结论就是将所有操作都用在一个数组上的答案一定最优,然后打个暴力发现是对的。
然后我们考虑如何动态维护前
由于空间给的比较小,所以要离散化。
代码
细节见代码。
#include <bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include <ext/rope>
using namespace __gnu_pbds;
using namespace std;
#define pb push_back
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define rep1(i,x,y) for(register int i=x;i>=y;--i)
#define ll long long
#define fire signed
#define il inline
template<class T> il void print(T x) {
if(x<0) printf("-"),x=-x;
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
template<class T> il void in(T &x) {
x = 0; char ch = getchar();
int f = 1;
while (ch < '0' || ch > '9') {if(ch=='-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= f;
}
int T=1;
const int N=2e5+10;
struct node{
int l,r;
int cnt;
ll sum;
}tr[N*20];
struct nodes{
int l;
vector<ll>v;
}s[N];
int n,m;
ll k,q;
int idx;
ll arr[N*2];
void up(int x) {
tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
tr[x].cnt=tr[x<<1].cnt+tr[x<<1|1].cnt;
}
void modify(int u,int l,int r,int x,int k) {
if(l==r) {
tr[u].cnt+=k;
tr[u].sum+=k*arr[x];
return;
}
int mid=l+r>>1;
if(mid>=x) modify(u<<1,l,mid,x,k);
else modify(u<<1|1,mid+1,r,x,k);
up(u);
}
ll Ans(int u,int l,int r,int k) {
if(l==r) {
return 1ll*arr[l]*min(k,tr[u].cnt);
}
int mid=l+r>>1;
if(tr[u<<1|1].cnt>=k) return Ans(u<<1|1,mid+1,r,k);
return Ans(u<<1,l,mid,k-tr[u<<1|1].cnt)+tr[u<<1|1].sum;
}
#define get(x) (lower_bound(arr+1,arr+1+idx,x)-arr)
void solve() {
in(n),in(m),in(q),in(k);
k=q*k;
rep(i,1,n) {
in(s[i].l);
rep(j,1,s[i].l) {
ll x;
in(x);
s[i].v.pb(x);
arr[++idx]=x;
arr[++idx]=x+k;
}
}
sort(arr+1,arr+1+idx);
idx=unique(arr+1,arr+1+idx)-arr-1;
rep(i,2,n) {
for(auto to:s[i].v) {
int it=lower_bound(arr+1,arr+1+idx,to)-arr;
modify(1,1,idx,it,1);
}
}
for(auto to:s[1].v) modify(1,1,idx,get(to+k),1);
ll res=Ans(1,1,idx,m);
rep(i,2,n) {
for(auto to:s[i-1].v) modify(1,1,idx,get(to+k),-1),modify(1,1,idx,get(to),1);
for(auto to:s[i].v) modify(1,1,idx,get(to+k),1),modify(1,1,idx,get(to),-1);
res=max(res,Ans(1,1,idx,m));
}
printf("%lld\n",res);
}
fire main() {
while(T--) {
solve();
}
return false;
}