Codeforces Round #632 (Div. 2) 比赛人数14824
[codeforces 1334C] Circle of Monsters 公式推导+变环形关系为直线关系+前缀和
总目录详见https://blog.csdn.net/mrcrack/article/details/103564004
在线测评地址https://codeforces.com/contest/1334/problem/C
Problem | Lang | Verdict | Time | Memory |
---|---|---|---|---|
C - Circle of Monsters | GNU C++17 | Accepted | 280 ms | 18800 KB |
比赛中一度以为该题做不出,不过,没有放弃,拿出纸笔,写写算算,不经意间,发现了该题的解决办法。
样例数据手工模拟如下
Input:
1
3
7 15
2 14
5 3
Output:
6
a1=7 b1=15
a2=2 b2=14
a3=5 b3=3
因(a2-b1)=(2-15)<0,故取值为a2-b1=0
因(a3-b2)=(5-14)<0,故取值为a3-b2=0
从位置1出发:消耗的子弹=a1+(a2-b1)+(a3-b2)=7+0+0=7
因(a3-b2)=(5-14)<0,故取值为a3-b2=0
因(a1-b3)=(7-3)>=0,故取值为a1-b3=4
从位置2出发:消耗的子弹=a2+(a3-b2)+(a1-b3)=2+0+4=6
因(a1-b3)=(7-3)>=0,故取值为a1-b3=4
因(a2-b1)=(2-15)<0,故取值为a2-b1=0
从位置3出发:消耗的子弹=a3+(a1-b3)+(a2-b1)=5+4+0=9
可以看到规律了:
a1+(a2-b1)+(a3-b2)
a2+(a3-b2)+(a1-b3)
a3+(a1-b3)+(a2-b1)
这3组数据中取最大值
环形的数据关系处理起来比较麻烦,怎么办呢,化成直线的数据关系,就容易处理了
接着上面的数据,继续分析
将数组由长度n串接为2*n,如何串接,请看如下分析。
位置 1 2 3 4 5 6
a a1 a2 a3 a1 a2 a3
b b1 b2 b3 b1 b2 b3
c a2-b1 a3-b2 a1-b3 a2-b1 a3-b2
前缀和sum 0 c2 c2+c3 c2+c3+c4 c2+c3+c4+c5 c2+c3+c4+c5+c6
a1+(a2-b1)+(a3-b2)=a1+(sum[3]-sum[1])
a2+(a3-b2)+(a1-b3)=a2+(sum[4]-sum[2])
a3+(a1-b3)+(a2-b1)=a3+(sum[5]-sum[3])
AC代码如下
#include <cstdio>
#include <algorithm>
#define maxn 600010
#define LL long long
using namespace std;
LL a[maxn],b[maxn],c[maxn],sum[maxn];
int main(){
int t,n,i;
LL mn;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
mn=1e18;//超出int范围的赋值
for(i=1;i<=n;i++)scanf("%lld%lld",&a[i],&b[i]);
for(i=n+1;i<=2*n;i++)a[i]=a[i-n],b[i]=b[i-n];//变环形为直线
for(i=2;i<=2*n;i++)c[i]=((a[i]>b[i-1])?(a[i]-b[i-1]):0);//爆炸对应的子弹消耗
sum[1]=0;
for(i=2;i<=2*n;i++)sum[i]=sum[i-1]+c[i];//前缀和
for(i=1;i<=n;i++)
mn=min(mn,a[i]+sum[i+n-1]-sum[i]);
printf("%lld\n",mn);
}
return 0;
}