题面

也就是说, 随机序列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);
}

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

  1. 11/5/2018模拟 Problem C

    题面 题解 我有特殊的哈希技巧 以到下一个相同字符的距离为值哈希, 如果不存在或在串外, 就是 \(|T| + 1\). 加入一个新字符 \(S_i\) 时, 同时修改它上一次出现时的值, 由 \(| ...

  2. 11.7 NOIP模拟赛

    目录 2018.11.7 NOIP模拟 A 序列sequence(two pointers) B 锁lock(思路) C 正方形square(埃氏筛) 考试代码 B C 2018.11.7 NOIP模 ...

  3. 11/1 NOIP 模拟赛

    11.1 NOIP 模拟赛 期望得分:50:实际得分:50: 思路:暴力枚举 + 快速幂 #include <algorithm> #include <cstring> #in ...

  4. 2018.11.6 PION 模拟赛

    期望:100 + 40 + 50 = 190 实际:60 + 10 + 50 = 120 考得好炸啊!!T1数组开小了炸掉40,T2用 int 读入 long long ,int存储 long lon ...

  5. 2018.11.5 PION模拟赛

    期望:30 + 40 + 50 = 120 实际:30 + 50 + 40 = 120 ‘’ 思路:最重要的是发现 是完全没有用的,然后这个题目就可以转成DP来做. /* 期望的分:30 */ #in ...

  6. 2018 11.1 PION 模拟赛

    期望:250  100+100+50 实际:210   80+100+30 期望:100   实际:80 最后:两个点T了.可能是求逆元的方法太慢了,也可能是闲的又加了一个快速乘的原因. #inclu ...

  7. 2018.11.08 NOIP模拟 班车(倍增+dfs+bit)

    传送门 对于每个点离线处理出向上走2i2^i2i班车到的最上面的点. 然后每个询问(u,v)(u,v)(u,v)先把(u,v)(u,v)(u,v)倍增到刚好走不到lcalcalca的情况(有一个点如果 ...

  8. 2018.11.08 NOIP模拟 水管(简单构造)

    传送门 仔细读题会发现只要所有点点权之和等于0一定有解. 如何构造? 直接当做树来构造就行了,非树边都赋值成0就行. 代码

  9. 2018.11.08 NOIP模拟 景点(倍增+矩阵快速幂优化dp)

    传送门 首先按照题意构造出转移矩阵. 然后可以矩阵快速幂求出答案. 但是直接做是O(n3qlogm)O(n^3qlogm)O(n3qlogm)的会TTT掉. 观察要求的东西发现我们只关系一行的答案. ...

随机推荐

  1. Item 25: 对右值引用使用std::move,对universal引用则使用std::forward

    本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 右值引用只能绑定那些有资格被move的对象上去.如 ...

  2. Linux查看端口

    1.lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000   2.netstat -tunlp |grep 端口号 用于查看指定的端口号的进程情况 ...

  3. C. Ayoub and Lost Array

    链接 [https://codeforces.com/contest/1105/problem/C] 题意 给你n,表示数组长度,元素的值是l到r,问有多少种方案使得所有元素和整除3 分析 思维dp, ...

  4. K 班1-7,alpha,beta 作业成绩汇总

    K 班1-7,alpha,beta 作业成绩汇总 千帆竞发 详细得分 短学号 名 1 2 3 4 5 6 7 alpha beta TOTAL 505 基智 4.55 1 -2 0 0 -10 4.3 ...

  5. 牛客练习赛B题 筱玛的排列(找递推规律)

    链接:https://ac.nowcoder.com/acm/contest/342/B来源:牛客网 筱玛的排列 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语 ...

  6. java 获取下一个字母(传大写返回大写,传小写返回小写)

    public static String getNextUpEn(String en){ char lastE = 'a'; char st = en.toCharArray()[0]; if(Cha ...

  7. MyEclipse 10.X激活方法

    普遍的激活办法请参考: http://blog.csdn.net/miss_kun/article/details/51819206 http://jingyan.baidu.com/article/ ...

  8. 【知乎】WinForm 与 WPF的区别

    你想上班 那么针对公司需求学如果只是自己写着玩 那么区分一下1.你的程序运行在 自己机器a.一个工具而已 要的是cooooooool 那么WPFb.一个工具而已 要的是useful easy 那么wi ...

  9. 下拉框、下拉控件之Select2

    一.Select2的功能简介 select2插件给我们带来了更加友好的交互方式,比如查询控件展开后可通过关键字进行检索 例如: Select2也可以选择带查询控件的选择框... Select2也可以选 ...

  10. 在Laravel中使用数据库事务以及捕获事务失败后的异常

    Description 在Laravel中要想在数据库事务中运行一组操作,则可以在 DB facade 中使用 transaction 方法.如果在事务的闭包内抛出异常,事务将会被自动还原.如果闭包运 ...