5.1培训考试二

今天小姐姐给了我们说良心很良心,说毒瘤很毒瘤的一套题(小姐姐说是可以AK的)

老师一定刚去看了复联4

据说这是道水题,一个set模拟就好了

来我们看看小姐姐的标程(仅限c++11)

#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;

class People {
    int id, force;
    People() {}
    People(int i, int f): id(i), force(f) {}//构造函数,意思是把id赋值为i,把force赋值为f
};

bool operator <(People x, People y) {
    return x.force < y.force;
}

int n;
set <People> s;


int main() {
    scanf("%d", &n);
    s.insert(People(1, 1000000000));
    for (int i = 1, x, y; i <= n; ++i) {
        scanf("%d%d", &x, &y);
        auto it1 = s.upper_bound(People(x, y));//找到第一个大于当前能力的人,这里返回的是指针
        if (it1 == s.begin()) printf("%d %d\n", x, it1->id);//如果是第一个人,就让他和超人比
        else {
            auto it3 = it1;
            auto it2 = --it3;//上面的数的前一个数的指针
            int a1 = abs(it1->force - y);//与第一个大于其的数的能力值比较
            int a2 = abs(it2->force - y);//和it2指向的数的能力值比较
            if (a2 <= a1) it1 = it2;//选取最小的(这里依旧是指针)
            printf("%d %d\n", x, it1->id);//把那个数输出来
        }
        s.insert(People(x, y));//比较完后加入set
    }
    return 0;
}

bat-man:

60pts:

O(n^2)暴力枚举

80pts:

st表讲解(里面的程序没有加小姐姐的神奇输入输出,但主要部分就是里面的程序辣)

加了小姐姐的输入输出:

#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;

const int N = 1e7 + 5;

long long st[1<<23][23];
int n, m, a[N], ans[N];
int gen, cute1, cute2;
int number() {
    gen = (1LL * gen * cute1) ^ cute2;
    return (gen & (n - 1)) + 1;
}
int seach(int l,int r)
{  int t=log((double)(r-l+1))/log(2.0);
   return max(st[l][t],st[r-(1<<t)+1][t]);
}
int main() {
    scanf("%d%d", &n, &m);
    scanf("%d%d%d", &gen, &cute1, &cute2);
     for (int i = 1; i <= n; ++i)//小姐姐的输入输出
        a[i] = number(); 
    for(int i=1;i<=n;i++)
      st[i][0]=a[i];
      double sx=log((double) n)/log(2.0);
    for(int j=1;j<=sx;j++)//剩下的就是st表了qwq
     { for(int i=1;(i+(1<<j))-1<=n;i++)
      {st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
      }
     }
    for (int i = 1; i <= m; ++i) {
        int l = number(), r = number();
        if (l > r) swap(l, r);
         ans[i]=seach(l,r);
    }
    int sum = 0;
    
    for (int i = 1; i <= m; ++i)
        sum = (1LL * sum * cute1 + ans[i]) % cute2;
    printf("%d\n", sum);
}

100pts:

我们使用并查集。

 小姐姐的代码(看不懂QwQ嘤~)

#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int N = 1e7 + 5;

int n, m;
int gen, cute1, cute2;
int number() {
    gen = (1LL * gen * cute1) ^ cute2;
    return (gen & (n - 1)) + 1;
}


int hd[N], nxt[N], id[N], to[N], cnt;
int ans[N], a[N], p[N], q[N];

int add(int x, int y, int i) {
    ++cnt;
    nxt[cnt] = hd[x];
    to[cnt] = y;
    id[cnt] = i;
    hd[x] = cnt;
}


int getfa(int x, int y) {
    int fa = x;
    for (int i = x; i; i = p[i])
        if (p[i] < y || p[i] == i) {
            fa = i;
            break;
        }
    for (int j, i = x; i != fa; i = j) {
        j = p[i], p[i] = fa;
    }
    return fa;
}

int main() {
    scanf("%d%d", &n, &m);
    scanf("%d%d%d", &gen, &cute1, &cute2);

    for (int i = 1; i <= n; ++i)
        a[i] = number();
    for (int i = 1; i <= m; ++i) {
        int l = number(), r = number();
        if (l > r) swap(l, r);
        add(l, r, i);
    }
    double t1;
    fprintf(stderr, "%lf\n", t1 = (double)clock()/CLOCKS_PER_SEC);

    int ind = 0;
    for (int i = 1; i <= n; ++i) {
        while (ind && a[q[ind]] <= a[i]) --ind;
        if (ind) p[i] = q[ind];
        else p[i] = i;
        q[++ind] = i;
    }

    for (int i = n; i; --i) {
        for (int j = hd[i]; j; j = nxt[j])
            ans[id[j]] = a[getfa(to[j], i)];
    }


    fprintf(stderr, "%lf\n", (double)clock()/CLOCKS_PER_SEC - t1);

    int sum = 0;
    for (int i = 1; i <= m; ++i)
        sum = (1LL * sum * cute1 + ans[i]) % cute2;
    printf("%d\n", sum);
}

猜你喜欢

转载自www.cnblogs.com/lcez56jsy/p/10813792.html
5.1