NOIP模拟题——麻耶

【问题描述】

油库里是幻想乡特有的一种生物。每只油库里都有一个战斗力值和一个能量值。当两只油库里战斗时,总是战斗力值高的一位获胜。获胜者的战斗力值将变成自己的原战斗力值-对手的战斗力值+对手的能量值。败者将死去。若两者战斗力值一样,则同归于尽。

思考熊发现了很多油库里,他想知道通过互相战斗之后油库里中战斗力值+能量值最高的一个可能到达多少。你能帮他们求出来吗?(假设除了考察的那只油库里之外,其他油库里之间不会发生战斗)

【输入格式】

第一行是一个整数N,代表当前有多少油库里。

接下来的N行,每一行有两个整数u,v,代表这只油库里的战斗力值和能量值。

【输出格式】

输出一个整数,代表油库里中的战斗力值+能量值最高的一个能达到多少。

【样例输入】

2

1 2

2 1

【样例输出】

4

【数据规模与约定】

对于 100%的数据, 1≤u,v≤10^9,1<=N<=10^5。

数据范围可得算法为O(n)/O(nlogn)。

可以得出,当油库里可以攻击另一个油库里,且另一个油库里的攻击力<这只油库里的能量值,则杀掉他一定是优的

考虑排序,将杀掉更优的所有油库里排序

对于油库里i,找到所有攻击力比他小的,加上他们的能量值和攻击力的差值、

此时攻击力会上升,则继续找,直到攻击力无法上升为止。可以用前缀和加二分实现。

如果这个油库里杀掉别的油库里,且这个油库里在更优的油库里中,则他杀掉了自己,二分中减去即可。

所以下一次的left就为right,因为攻击力是递增的。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int maxn=1e5+7;
 7 long long a[maxn],b[maxn];
 8 long long c[maxn];
 9 struct node{
10     long long q,w;
11 }r[maxn];
12 int temp=0;
13 int n;long long ans=0;
14 bool comp(const node &qw,const node &we)
15 {
16     return qw.q<we.q;
17 }
18 long long max(long long x,long long y)
19 {
20     if(x<y)return y;
21     return x;
22 }
23 int main()
24 {
25     freopen("zyougamaya.in","r",stdin);
26     freopen("zyougamaya.out","w",stdout);
27     scanf("%d",&n);
28     for(int i=1;i<=n;i++)
29     {
30         scanf("%I64d%I64d",&a[i],&b[i]);
31         if(a[i]<b[i])
32         {
33             r[++temp].q=a[i];
34             r[temp].w=b[i]-a[i];
35         }
36     }
37     sort(r+1,r+temp+1,comp);
38     for(int i=2;i<=temp;i++)
39     r[i].w+=r[i-1].w;
40     for(int i=1;i<=n;i++)
41     {
42         long long x=a[i],y=b[i];long long pre=0;long long xx=a[i];int left=1,right=temp;
43         while(1)
44         {
45             int start=left;
46             while(left<=right)
47             {
48                 int mid=(left+right)>>1;
49                 if(r[mid].q<xx)
50                 left=mid+1;
51                 else right=mid-1;
52             }
53             if(r[right].q==xx)break;
54             if(right==start-1)break;
55             xx=x+r[right].w;
56             //if(a[i]<b[i])
57             //xx=xx+a[i]-b[i];
58             if(xx==pre)break;
59             pre=xx;
60             left=right;right=temp;
61         }
62         if(pre==0)//没重 
63         ans=max(ans,x+y);
64         else if(x-y<0)ans=max(ans,xx+y+x-y);
65         else ans=max(ans,xx+y);
66     }
67     printf("%I64d",ans);
68     return 0;
69 }
原文地址:https://www.cnblogs.com/937337156Zhang/p/6043705.html