无内鬼,来点主席树做法。
其实是因为不会 stl。
Solution
看这个连续区间加上,区间长度不限制,还有 $t$ 的单调性,考虑双指针。
那么复杂度瓶颈就在如何快速计算区间中前 $w$ 大的数的时间的一半。
区间前 $k$ 大,考虑主席树。
其实就是经典区间第 $k$ 大的变种,实现起来并不是特别困难。
时间复杂度 $O(n\log n)$ 。
Code
//#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define N 500005
using namespace std;
int read(){
int x=0,w=1;
char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x*w;
}
int n,w,k,tot,ans;
int root[N],t[N],sum[N],sum1[N],a[N];
struct node{int l,r,sum,val;}tree[N<<5];
void update(int &p,int l,int r,int x){
tot++;
tree[tot]=tree[p];tree[tot].sum++;tree[tot].val+=x/2;
p=tot;
int mid=(l+r)>>1;
if(l<r){
if(x<=mid) update(tree[p].l,l,mid,x);
else update(tree[p].r,mid+1,r,x);
}
}
int query(int t1,int t2,int l,int r,int k){
if(l>=r) return l/2*(tree[t1].sum-tree[t2].sum-k+1);
int x=tree[tree[t1].l].sum-tree[tree[t2].l].sum;
int y=tree[t1].val-tree[t2].val-(tree[tree[t1].l].val-tree[tree[t2].l].val);
int mid=(l+r)>>1;
if(x>=k) return query(tree[t1].l,tree[t2].l,l,mid,k)+y;
else return query(tree[t1].r,tree[t2].r,mid+1,r,k-x);
}
signed main(){
n=read();w=read();k=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i];
for(int i=1;i<=n;++i){
t[i]=read();
root[i]=root[i-1];
update(root[i],1,10000,t[i]);
}
for(int i=1;i<=n;++i) sum1[i]=sum1[i-1]+t[i];
int r=0;
for(int l=1;l<=n;++l){
while(r<n&&sum1[r+1]-sum1[l-1]-query(root[r+1],root[l-1],1,10000,r+3-l-min(w,r+2-l))<=k) r++;
ans=max(ans,sum[r]-sum[l-1]);
}
printf("%d\n",ans);
return 0;
}
因为一一些细节调了很久,可读性并不是很好,感性理解一下。