您的位置:首页 > 其它

HDU 6205 card card card【最长连续子串+尺取法】

2017-09-10 21:45 399 查看
题目链接

题意:n堆牌,每堆牌有个penalty value,刚开始可以把第一堆牌移到最后面,这个操作可以进行任意多次。然后从第一堆牌开始,每次加上这堆牌的数目减去这堆牌的penalty value,如果这个值小于0则取走到现在为止的所有牌,游戏结束。求刚开始时移第一堆的这个操作进行几次的时候可以拿走的牌最多。

其实就是一个变形版的最长连续子串,保证子串中每个前缀和都大于等于0,如果有一个小于0,这串就直接结束。此外,要保证子串的长度小于等于n。然后如果当前子串长度为n,就减去最开始那个看后面的加上后是否能满足,就是尺取法的思想。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

int n;
int num[2000000+10];
int cha[2000000+10];

int main(){
// freopen("1.txt","r",stdin);
while (scanf("%d",&n)!=EOF){
for (int i=1;i<=n;i++){
scanf("%d",&num[i]);
}
for (int i=1;i<=n;i++){
int x;
scanf("%d",&x);
cha[i]=num[i]-x;
}
for (int i=n+1;i<=2*n;i++){
num[i]=num[i-n];
cha[i]=cha[i-n];
}
ll begin=1,len=0,sum=0;
ll tmp=0;
int i=1;
int index=0;
ll MAX=0;
while (i<=2*n){
tmp+=cha[i];
sum+=num[i];
len++;
// printf("%d %lld %lld %lld\n",i,tmp,sum,len);
if (tmp<0){
if (sum>MAX){
MAX=sum;
index=begin;
}
begin=i+1;
sum=0;
len=0;
tmp=0;
i++;
continue;
}
else{
if (len==n){
if (sum>MAX){
MAX=sum;
index=begin;
}
sum-=num[begin];
tmp-=cha[begin];
len--;
begin++;
}
else{
if (sum>MAX){
MAX=sum;
index=begin;
}
}
i++;
}
}
if (index>n){
index-=n;
}
index--;
printf("%d\n",index);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: