Codeforces Round #799 (Div. 4) H. Gambling

翻译:

玛丽安在赌场。赌场里的游戏是这样的。

在每一轮之前,玩家在1到109之间选择一个数字。在那之后,一个有109个面的骰子被滚动,这样就会出现1到109之间的随机数。如果玩家猜对了数字,他们的钱就会翻倍,否则他们的钱就会减半。

玛丽安预测了未来,知道所有的数字𝑥1,𝑥2,…,𝑥𝑛,骰子将显示在接下来的𝑛轮。

他将选择三个整数𝑎、𝑙和𝑟(𝑙≤𝑟)。他将玩𝑟−𝑙+1轮(包括𝑙和𝑟之间的回合)。在每一轮比赛中,他都会猜出相同的数字𝑎。开始时(在一轮𝑙之前)他有1美元。

Marian让你确定整数𝑎,𝑙和𝑟(1≤𝑎≤109,1≤𝑙≤𝑟≤𝑛),这样他最后赚的钱最多。

注意,在对半和乘法过程中没有舍入和精度误差。例如,在一场游戏中,Marian的钱可能等于11024、1128、12、1、2、4等(任何2𝑡的值,其中𝑡是任意符号的整数)。

输入
第一行包含一个整数𝑡(1≤𝑡≤100)——测试用例的数量。

每个测试用例的第一行包含单个整数𝑛(1≤𝑛≤2⋅105)——轮数。

每个测试用例的第二行包含𝑛整数𝑥1,𝑥2,…,𝑥𝑛(1≤𝑥𝑖≤109),其中𝑥𝑖是将落在𝑖-th轮骰子上的数字。

保证𝑛在所有测试用例上的总和不超过2⋅105。

输出
对于每个测试用例,输出三个整数𝑎、𝑙和𝑟,这样Marian就可以用他的策略赌博赚最多的钱。如果有多个答案,您可以输出其中任何一个。

例子
inputCopy
4
5
4 4 3 4 4 4
5
11 1 11 1 11
1
1000000000
10
8 8 8 9 9 6 6 9 6 6
outputCopy
4 1 5
1 2 2
1000000000 1 1
6 6 10
请注意
对于第一个测试用例,最佳选择是𝑎=4,𝑙=1,𝑟=5,游戏将如下所示。

玛丽安从一美元开始。
第一轮之后,他得到了2美元因为数字与选中的数字一致。
第二轮之后,他得到4元,因为数字又重合了。
第三轮之后,他得到2元,因为他猜的是4,尽管3是正确选项。
第四轮之后,他又得到4元。
最后一轮,他得到8元,因为他猜对了。
对于第二个测试用例有许多可能的答案,但是可以证明Marian最终不会得到超过2美元,因此任何带有适当𝑎的𝑙=𝑟的选择都是可以接受的。

思路:每次符合乘2,不符合就除2,最优的情况肯定是以一个数字,为边界,里面此数字比较多,这样才能抵消掉不符合的,所以我们直接存每个数的下标,相同的存在一起,最后直接遍历,找最大的。

代码:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}


void solv(){
    cin>>n;
    vector<int>a(n+1);
    map<int,vector<int>>q;
    for (int i=1; i<=n; i++) {
        cin>>a[i];
        q[a[i]].push_back(i);
    }
    int sz=a[1],l=1,r=1;
    int an=1;
    for (auto [x,y]:q) {
        int beg=y[0];
        int l1 =0;
        for (int i =1; i<y.size(); i++) {
            if (2*(i-l1)+1-y[i]+beg<1) {
                beg=y[i];
                l1=i;
                continue;
            }
            if ((2*(i-l1+1)-y[i]+beg)>an) {
                an= 2*(i-l1)+1-y[i]+beg;
                l=beg;
                r=y[i];
                sz=x;
            }
        }
    }
    printf("%d %d %d\n",sz,l,r);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    while (t--) {
        solv();
    }
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值