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);
}
11/1/2018模拟 Max的更多相关文章
- 11/5/2018模拟 Problem C
题面 题解 我有特殊的哈希技巧 以到下一个相同字符的距离为值哈希, 如果不存在或在串外, 就是 \(|T| + 1\). 加入一个新字符 \(S_i\) 时, 同时修改它上一次出现时的值, 由 \(| ...
- 11.7 NOIP模拟赛
目录 2018.11.7 NOIP模拟 A 序列sequence(two pointers) B 锁lock(思路) C 正方形square(埃氏筛) 考试代码 B C 2018.11.7 NOIP模 ...
- 11/1 NOIP 模拟赛
11.1 NOIP 模拟赛 期望得分:50:实际得分:50: 思路:暴力枚举 + 快速幂 #include <algorithm> #include <cstring> #in ...
- 2018.11.6 PION 模拟赛
期望:100 + 40 + 50 = 190 实际:60 + 10 + 50 = 120 考得好炸啊!!T1数组开小了炸掉40,T2用 int 读入 long long ,int存储 long lon ...
- 2018.11.5 PION模拟赛
期望:30 + 40 + 50 = 120 实际:30 + 50 + 40 = 120 ‘’ 思路:最重要的是发现 是完全没有用的,然后这个题目就可以转成DP来做. /* 期望的分:30 */ #in ...
- 2018 11.1 PION 模拟赛
期望:250 100+100+50 实际:210 80+100+30 期望:100 实际:80 最后:两个点T了.可能是求逆元的方法太慢了,也可能是闲的又加了一个快速乘的原因. #inclu ...
- 2018.11.08 NOIP模拟 班车(倍增+dfs+bit)
传送门 对于每个点离线处理出向上走2i2^i2i班车到的最上面的点. 然后每个询问(u,v)(u,v)(u,v)先把(u,v)(u,v)(u,v)倍增到刚好走不到lcalcalca的情况(有一个点如果 ...
- 2018.11.08 NOIP模拟 水管(简单构造)
传送门 仔细读题会发现只要所有点点权之和等于0一定有解. 如何构造? 直接当做树来构造就行了,非树边都赋值成0就行. 代码
- 2018.11.08 NOIP模拟 景点(倍增+矩阵快速幂优化dp)
传送门 首先按照题意构造出转移矩阵. 然后可以矩阵快速幂求出答案. 但是直接做是O(n3qlogm)O(n^3qlogm)O(n3qlogm)的会TTT掉. 观察要求的东西发现我们只关系一行的答案. ...
随机推荐
- hbuilder IOS APP 打包与发布2
在上一篇的<hbuilder IOS APP 打包与发布>中,请求 的 是APP ids . ios开发证书 .和开发配置文件 , 这一篇中就不写发布证书和配置文件的请求,因为流程 ...
- 如果IBM再给我一次实习机会
2014年,我拿到了IBM斯图加特R&D的实习机会.在连续被索尼和博世拒掉之后,这个实习对我来说弥足珍贵.我学的是通信专业,在这之前与编程相关的活动只有一学期的安卓Lab,还是靠抱队友大腿才及 ...
- 一篇 JPA 总结
概述 下面是 JDBC 在 Java 应用和数据库之间的位置,充当着一个中间者,供 Java 应用程序访问所有类别的数据库,建立一个标准 JPA 如同 JDBC 一样,为 Java 应用程序使用 OR ...
- 个人实战演练全过程——No.1 最大连续子数组求和
之前的一次个人总结和一次单元测试入门学习是开启软件工程课程的前奏曲,也是热身,现在大家对于这门课程也有了初步的了解和认识,这次要开始真正的演奏了,要从头到尾完全靠自己的能力来解决一个问题,进行实战演练 ...
- H5 详情和概要标签
38-详情和概要标签 概要信息 详情信息 --> 郑伊健 简介:郑伊健,1967年10月4日出生于中国香港,籍贯广东恩平,香港影视演员.流行男歌手.1988年参加新秀歌唱大赛加入无线电视,因拍摄 ...
- 001-电脑操作规范-2019年03月.doc
001-电脑操作规范-2019年03月.doc 本文作者:徐晓亮 BoAi 作者腾讯QQ号码:595076941 /////////////////////////////////////// ...
- 整数划分 poj3181
分析 因为n,m分别最大1000,100 所以结果会超过ll,要用两个来存大数的两部分 代码 #include<iostream> #include<algorithm> #i ...
- MySQL中有关NULL的计算
mysql> select NULL=NULL; #判断两个NULL是否相等,结果不是1也不是0 +-----------+ | NULL=NULL | +-----------+ | NULL ...
- Linux sudoers
xxx is not in the sudoers file.This incident will be reported.的解决方法 - xiaochaoyxc - 博客园http://www.cn ...
- .net 报错汇总——持续更新
1.未能找到 CodeDom 提供程序类型“Microsoft.CodeDom.Providers.DotNetCompilerPla PM> Install-Package Microsoft ...