题意:
Sasha开着她的车去工作,在上班路上她想听听音乐。现在她的歌单里有n首歌,规定听完第i首,Sasha能获得ai点快乐度,,Sasha当然是想获得最大的快乐度啦。。。
不过这个问题有些限制。Sasha不能一直听音乐,因为开车ks后她就会到工作点,而第i首歌耗时tis。Sasha能获得一首歌的快乐度当且仅当她听完整首歌。特别地,Sasha有w次机会,选择w首歌,只需听[ai/2](上取整)就能获得那首歌的快乐度
Sasha可以任意选择第x首歌,从这里开始听,但是从这以后不能再跳过任何一首歌。现在Sasha想要你帮忙,,给她设计一个方案使得最终获得的快乐度最大。 n <= 2E5
solution:
虽然想到了解但是场内码不完。。。假设Sasha从第x首歌开始听,因为中途不允许跳歌,所以时间减半的机会当然是都留给单曲耗时最长的w首歌曲啦。再设如果Sasha从第x首歌开始听,最多能听到第y首,那么,如果Sasha从第x+1首开始听,至少能听到第y首。也就是说,这玩意满足决策单调性
剩下的就是时时刻刻维护耗时最长的w首歌了。这里提供一种用两个堆维护的做法
首先,令x = 1,尽可能多的塞歌进去,作为初始状态
在x不断右移的时候,先删除x - 1对答案的影响,这里维护两个堆,Q1:存放当前耗时最长w首歌,Q2:存放除了那w首歌,其它在当前选定集合的歌。删除x - 1对答案的影响,若x - 1本来在Q1,那么从Q2中找到最大的填进去。右指针如果想右移,先看Q1中最短的歌是不是比它短,是就能替换,被替换的进入Q2。因此,前者小根堆,后者大根堆。因为涉及元素删改操作,可用配对堆实现。(平板电视大法好)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 2E5 + 20;
struct data{
int num,ti; data(){}
data(int num,int ti): num(num),ti(ti){}
bool operator < (const data &b) const {return ti < b.ti;}
bool operator > (const data &b) const {return ti > b.ti;}
};
typedef __gnu_pbds::priority_queue<data,greater<data>,__gnu_pbds::pairing_heap_tag> Hp1;
typedef __gnu_pbds::priority_queue<data,less<data>,__gnu_pbds::pairing_heap_tag> Hp2;
int n,w,k,ans,sa,st,R,tot,a[maxn],t[maxn];
bool inq[maxn];
Hp1 Q; Hp2 Q2;
Hp1::point_iterator id[maxn];
Hp2::point_iterator id2[maxn];
bool Add(int x)
{
int now = st;
if (tot < w)
{
now += (t[x] + 1) / 2;
if (now > k) return 0;
st = now; sa += a[x];
ans = max(ans,sa); ++tot;
id[x] = Q.push(data(x,t[x]));
inq[x] = 1; return 1;
}
else
{
data G = Q.top();
if (G.ti < t[x])
{
now -= (G.ti + 1) / 2;
now += G.ti; now += (t[x] + 1) / 2;
if (now > k) return 0;
st = now; sa += a[x];
ans = max(ans,sa);
Q.pop(); inq[G.num] = 0;
id[x] = Q.push(data(x,t[x]));
id2[G.num] = Q2.push(G);
inq[x] = 1; return 1;
}
else
{
now += t[x];
if (now > k) return 0;
st = now; sa += a[x];
ans = max(ans,sa);
id2[x] = Q2.push(data(x,t[x]));
return 1;
}
}
}
void Erase(int x)
{
sa -= a[x];
if (inq[x])
{
st -= (t[x] + 1) / 2;
Q.erase(id[x]);
inq[x] = 0; --tot;
}
else st -= t[x],Q2.erase(id2[x]);
while (tot < w && !Q2.empty())
{
data G = Q2.top(); Q2.pop();
st -= G.ti; st += (G.ti + 1) / 2;
++tot; id[G.num] = Q.push(G); inq[G.num] = 1;
}
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n >> w >> k;
for (int i = 1; i <= n; i++) scanf("%d",&a[i]);
for (int i = 1; i <= n; i++) scanf("%d",&t[i]);
int R = 0; while (R < n && Add(R + 1)) ++R;
for (int i = 2; i <= n; i++)
{
Erase(i - 1);
while (R < n && Add(R + 1)) ++R;
}
cout << ans;
return 0;
}