[NOIP模拟][简单]T1-举办比赛

[NOIP模拟][简单] T1–举办比赛


阅读本文推荐BGM :너를 보네 (看到你了) - 박별

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=453927842&auto=1&height=66">

题目描述 :

    Mstdream 举办了一场抢答比赛!
    这场抢答比赛有 n 支队伍参赛,第 i 支队伍将会被分配一个随机值 si, 每一个问题, si 值较小的队伍会拥有优先发言权, 于是 Mstdream 想知道所有队伍最小的 si 值, 以便统计 。
    但是,由于各种各样的原因,一些队伍的 si值会变化,Mstdream想让你帮忙,对于每次修改后求出所有队伍中最小的 si 值 。
由于队伍实在太多了!我们将采用数据生成的方式读入数据
我们将给出n, m, x0, x1, a, b, c七个数,对于 c++ 语言,我们将采用如下读入 :

#define uint unsigned int 
uint x0, x1, a, b, c, n, m; 
uint now = 1, tot = 0; 
uint s[10000010]; 
uint nxt(){ 
    uint t = x0 * a + x1 * b + c; 
    x0 = x1; 
    x1 = t; 
    return x0 >> 2; 
} 
int main(){ 
    std::cin>>n>>m>>x0>>x1>>a>>b>>c; 
    for(int i = 0; i < n; ++i){ 
        s[i] = 2147483647; 
    } 
    for(int i = 1; i <= m; ++i){ 
    int f = nxt(); 
    int g = nxt(); 
    int ps = f % n; 
    s[ps] = g;  //此处是修改 
    uint ans = 0; 
    //......此处需要你求出 s[0] 到 s[n-1] 的最小值, 并且存在 ans 当中 
    now *= 10099; 
    tot += now*ans; 
    } 
    std::cout<<tot<<std::endl; 
} 

根据相关理论, nxt()函数是随机的。
Input
  7个数n,m,x0,x1,a,b,c
Output
  一个数,即程序中的tot值

Sample Input

5 5 1 2 3 4 5

Sample Output

3818396440

Sample Input

10000000 10000000 555 888 777 666 12345

Sample Output

4134418848

范围 :

10% n, m <= 1000
40% n, m <= 100000
100% n <= 10000000, m <= 50000000
保证 x0, x1, a, b, c 在 unsigned int 范围内

Time Limit: 4 Sec
Memory Limit: 512 MB

谈一谈我的想法:

    初看这道题, 哦,求最小值带修改,那直接线段树啊。咦,等等,范围 5e7,这怎么办,不管了先打一通,果然线段树果然爆栈,完了完了我要爆在第一题了,讲真说好的可以AK呢,但是这么着急也不是办法, 冷静下来再看一看题,咦,等等, nxt 函数随机啊(虽然是规则的随机), 再算了算期望不大啊,好像可以暴力搞啊。于是打了打,大样例只有 1.09 Sec 很友善啊, 最后评测的时候虽然慢了一点,但还是过了。

简单理一下 :
    这道题呢时限开得很大, 给你一个小小的暗示: 暴力, 记录当前序列中的最小值,简单维护: 如果当次操作改变的正好是当前的最小值,就对整个序列从头到尾扫一遍,维护最小,如果不是修改的当前最小值, 就直接与当前最小值比较维护最小, 完了!!

    考虑期望对于每次操作选择序列中随机的一个数, 操作一共 5e7 次, 期望选中同一个数为 m / n = 5, 所以不会 T 掉。

下面贴出代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <ctime>
#include <map>
#include <vector>
#define uint unsigned int
using namespace std;

uint x0, x1, a, b, n, m, c;
uint now = 1, tot = 0;
uint s1[10000010];
uint nxt() {
    uint t = x0 * a + x1 * b + c;
    x0 = x1;
    x1 = t;
    return x0 >> 2;
}

int main() {
    cin>>n>>m>>x0>>x1>>a>>b>>c;
    for(int i = 0; i < n; ++i) s1[i]= 2147483647;
    int o = 0;
    for(int i = 1; i <= m; ++i) {
        int f = nxt();
        int g = nxt();
        int ps = f % n;
        s1[ps] = g;
        uint ans = 0;
        if(o == ps) {
            uint now = 0x3f3f3f3f;
            for(int i = 0; i < n; ++i) {
                if(now > s1[i])
                    now = s1[i], o = i;
            }
        }
        else 
            if(s1[ps] < s1[o]) o = ps;
        ans = s1[o];
        now *= 10099;
        tot += now * ans;
    }
    cout<<tot;
}

本题结束
是不是要犒劳自己一曲音乐呢:Still Worth Fighting For - My Darkest Days

border="0" width="330" height="86" src="//music.163.com/outchain/player?type=2&id=4195988&auto=0&height=66">



感谢阅读本篇文章,喜欢的话,点个赞吧,你的鼓励就是我最大的动力

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值