11/1/2018模拟 Max

题面

也就是说, 随机序列RMQ.(\(n \le 8388608\), \(m \le 8*10^6\))

解法

我写了笛卡尔树+tarjan

然而听神仙说, 因为数据随机, 建完树暴力找lca就行, 跑的飞快...吊打std...

还有题解, 真是神仙做法...

设 \(p_i\) 表示比 \(a_i\) 大的前一个数所在的位置,那么 p 构成了一棵树。
若我们需要查询 [l, r] 的答案,只需找到 r 在这棵树上不小于 l 的祖先。于是我们可以按照 l
从大到小排序,一边向上查询祖先一边路径压缩(类似并查集)。
由于树上的每条边至多被压缩一次,复杂度 O(n) 。

我的代码:


#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
#define rep(i,l,r) for(register int i=(l);i<=(r);++i)
#define repdo(i,l,r) for(register int i=(l);i>=(r);--i)
#define il inline
typedef double db;
typedef long long ll;

//---------------------------------------
int n,m;
int gen,p1,p2;
int number(){
    gen=(1LL*gen*p1)^p2;
    return (gen&(n-1))+1;
}
const int nsz=8388700;
int a[nsz],ans[nsz];

struct tnd{int ch[2];}car[nsz];
int rt,pc=0;
int stk[nsz],top=0;
void build(){
    rep(i,1,n){
        while(top&&a[stk[top]]<a[i])car[i].ch[0]=stk[top--];
        car[stk[top]].ch[1]=i;
        stk[++top]=i;
    }
    rt=stk[1],pc=n;
}

struct tq{int t,pr;}qu[nsz*2];
int hd[nsz],pq=1;
void adde(int f,int t){qu[++pq]=(tq){t,hd[f]};hd[f]=pq;}
void adddb(int f,int t){adde(f,t);adde(t,f);}

int fa[nsz];
void init(){rep(i,1,n)fa[i]=i;}
void merge(int a,int b){fa[b]=a;}
int find(int p){return p==fa[p]?p:fa[p]=find(fa[p]);}

int vi[nsz];
void tar(int p){
    vi[p]=1;
    int v;
    rep(i,0,1){
        v=car[p].ch[i];
        if(v==0)continue;
        tar(v);
        merge(p,v);
    }
    for(int i=hd[p];i;i=qu[i].pr){
        if(vi[qu[i].t])
            ans[i/2]=find(qu[i].t);
    }
}
int main() {
//  freopen("max.in", "r", stdin);
//  freopen("max.out", "w", stdout);

    scanf("%d%d", &n, &m);
    scanf("%d%d%d", &gen, &p1, &p2);
    for (int i = 1; i <= n; ++i)
        a[i] = number();
    int l,r;
    for (int i = 1; i <= m; ++i) {
        l = number(), r = number();
        if (l > r) swap(l,r);
        adddb(l,r);
    }

    build();
    init();
    tar(rt);

    ll sum = 0;
    for (int i = 1; i <= m; ++i) {
        sum=(sum+a[ans[i]])%p2;
    }
    sum=sum*p1%p2;
    printf("%lld\n", sum);
}

std:

#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() {
    freopen("max.in", "r", stdin);
    freopen("max.out", "w", stdout);

    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 * ans[i] * cute1 % cute2) %= cute2;
    printf("%d\n", sum);
}

原文地址:https://www.cnblogs.com/ubospica/p/9889464.html

时间: 2024-11-03 12:50:33

11/1/2018模拟 Max的相关文章

2017 11.6 NOIP模拟赛

1.数学老师的报复(attack.pas/c/cpp)[问题描述]11 班数学大佬 YXN 又在上数学课的时候把班主任 MP6 的错误当众挑出来了,MP6 再一次感到很难堪,于是决定报复 YXNMP6 对 YXN 说:给你一个函数 f(x),定义如下:f ( 1 ) = 1f ( 2 ) = 1f ( n ) = ( A * f ( n - 1 ) + B * f ( n - 2 ) ) mod 7.YXN 说这还不简单,可以秒杀!MP6 微微笑了笑说:n 等于 100 你算得出来,那 n 等于

Test on 11/4/2018

来浙理的第一次月赛,嗯我是被大佬吊着打的垃圾. A:优美数 Description 如果一个数中只有少于三个数字是非零的,那么我们称这个数为优美数,我们定义这个优美数的优美程度为这个数所有数字相加的和. 例如优美数有4,200000,10203,其中4的优美度是4,200000的优美度是2,10203的优美度是6. 数字4231,102306,7277420000,就不是啰. 现在问在[L,R]中,有多少个优美度为x的优美数. Input T组数据,T<=5e4. 第一行为组数T. 接下来T行,

java 22 - 11 多线程之模拟电影院售票口售票

使用多线程实现的第二种方式: 首先创建自定义类 1 public class SellTicket implements Runnable { 2 // 定义100张票 3 private int ticket = 100; 4 5 public void run() { 6 7 //假设一直在售票 8 while(true){ 9 //现实中买票时,都会有延迟的,所以让线程休息下 10 try { 11 Thread.sleep(100); 12 } catch (InterruptedExc

11.13 noip模拟试题

题目名称 笔记 括号 城堡可执行文件名 note brackets castle输入文件名 note.in brackets.in castle.in输出文件名 note.in brackets.out castle.in每个测试点时限 1 秒 1 秒 1 秒内存限制 512MB 512MB 512MB测试点数目 20 20 10每个测试点分值 5 5 10是否有部分分 否 否 否题目类型 传统型 传统型 传统型测试题 #4 笔记笔记[问题描述]给定一个长度为?的序列?,下标编号为1~?.序列的

11.12 noip模拟试题

题目名称 加密 冒泡排序图 重建可执行文件名 encrypt bubble rebuild输入文件名 encrypt.in bubble.in rebuild.in输出文件名 encrypt.in bubble.out rebuild.in每个测试点时限 1 秒 1 秒 1 秒内存限制 512MB 512MB 512MB测试点数目 10 20 10每个测试点分值 10 5 10是否有部分分 否 否 否题目类型 传统型 传统型 传统型测试题 #3 加密 加密[问题描述]有一种不讲道理的加密方法是:

2017.11.7~8模拟测试总结---暨NOIP2017考前对策

最后两天了,第三天就是NOIP2017--Day1了. 刚刚考完了这个学期从开学以来的最后一场模拟赛了.首先要对于这场模拟赛做一次深刻的反思. 考完才猛地惊叹这是最后一场模拟赛了,然而题目并不难,也保留了T1送分的原则,但是这场考试下来,很多地方都是不尽人意的.两天的T2要好好反思反思,自己为什么就会把简简单单的问题去想得那么的复杂啊!思维要活跃起来. 譬如Day1T2,纵使最后刚出来了(其实是调了很久)为什么调了很久呢?一个树形DP,被自己想成贪心,虽然是对的,但是代码从五六十行到了一百二三十

11/15 2018

时间: 晚上7:53 地点:住处 设计模式只是一些套路,或者说是经验的总结,盲目的套用设计模式并非好处,所有的设计应该保持简单,只有需要实践扩展的时候才值得使用复杂性和模式,应当分辨出来再什么时候使用模式,或者说什么时候需要模式,判断当前模式是否符合当前情况,是否要恰当的修改以便其适应. 作为开发人员来说,应该着重于最能解决问题的简单方案,考虑对象的原则,以及折衷,模式只是方案,不能过度的影响到设计的决策 时间: 晚上8:20分 阅读winner个人经历有感 winner 原文地址:https:

Test on 11/17/2018

第一次参加cf比赛,水了一发写了三道水题实在不想写了,然后Rating就低了,好难过哈哈哈哈. cf#521(div.3) D:Cutting Out Description You are given an array ss consisting of nn integers. You have to find any array tt of length kk such that you can cut out maximum number of copies of array tt fro

2019/3/11 省选模拟总结

题面/题解:https://files.cnblogs.com/files/Harry-bh/problemset%281%29.rar T1.树上四次求和 主要考察了,对计数问题的分析,动态点分治的应用. 考试的时候因为边的数组开小了所以导致只得了暴力的分,以后一定要留意. 掌握程度 动态点分治:????? 计数问题:?? (推的时候很不熟练,差点没想到) T2.Cubelia 这是一道看起来比较简单的题,这也就导致了我花了大量时间来做这道题(结果考完后发现这道题最难?) 所以这体现了我考试经