t(t<=10)组样例,每次给出n(n<=2e5)个人,
第i个人有hi(hi<=2e5)条命,每条命有ai(ai<=2e5)点血
当对人造成x点伤害时,如果x<当前血量,血量减少x,否则,扣掉一条命,令血量回满
游戏开始时,你可以设置一个正整数x,
然后每一轮,对所有玩家都造成x点伤害,
当所有玩家阵亡时,游戏结束,游戏结束时结算得分
最后阵亡的玩家,假设在第a轮阵亡,而倒数第二个阵亡的玩家,假设在第b轮阵亡,
则最后阵亡的玩家的分数为a-b(a=b时,得分为0),其他玩家的分数为0
对于每个玩家i,独立地求,正整数x任意设置时,玩家i能获得的最大得分
jiangly代码/nanami代码
简单手玩后发现, 每个人能坚持的轮数是,
所以,可以枚举每个x,对于x倍数枚举y,
对于[1,y]内的值v来说,是相同的,区间求一下h的最大值(需要值对应的所在位置)
区间求最大值,st表O(nlogn)预处理一下,然后O(1)求,总复杂度O(nlogn)
仔细思考后发现,ST表的过程是没有必要的,
实际只需要从大到小扫一遍,维护后缀最大值即可
因为一个值(hi,ai),
在小于ai的地方被枚举到的话,只会不超过答案
而在ai的地方被枚举到的时候,等于答案的值可以取到,
也就意味着可以取到最大值,
所以,扫两遍,第一遍求最大值,第二遍求次大值
#include
using namespace std;
#define ll long long
#define MP make_pair
mt19937 rnd(time(0));
const int MAXN=4e5+5;
const int lim=2e5;
ll a[MAXN],h[MAXN],n,lg[MAXN];
ll ans[MAXN];
struct node{int x,y;}s[20][MAXN];
node operator +(node x,node y){
for(int i:{y.x,y.y})if(i&&i!=x.x&&i!=x.y){
if(h[x.x]>n;
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;ival(mx1)) mx2=mx1,mx1=j;
else if(val(j)>val(mx2)) mx2=j;
}
}
// cout<>1]+1;
int _;cin>>_;
while(_--) solve();
}
#include
//#include
//#include