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掉. 观察要求的东西发现我们只关系一行的答案. ...
随机推荐
- BZOJ3199 SDOI2013 逃考 半平面交、最短路
传送门 如果我们对于每一个点能找到与其相邻的点(即不经过其他点监视范围能够直接到达其监视范围的点)和是否直接到达边界,就可以直接BFS求最短路求出答案. 所以当前最重要的问题是如何找到对于每一个点相邻 ...
- Arduino通过MAX9814实现录音
如果通过Arduino进行录音不是单纯地接一个驻极电容MIC就可以的,因为自然界中的声音非常复杂,波形极其复杂,通常我们采用的是脉冲代码调制编码.即PCM编码.PCM通过抽样.量化.编码三个步骤将连续 ...
- 算法题:合并N个长度为L的有序数组为一个有序数组(JAVA实现)
昨天面试被问到这道算法题,一时没有回答上来,今天思考了一下,参阅了网上的教程,做了一个JAVA版本的实现. 方案一: 新建一个N*L的数组,将原始数组拼接存放在这个大数组中,再调用Arrays.sor ...
- Javascript 综合示例 网页扫雷游戏
---------------认定了的事情,只要是对的,干到底! ------------------------------------------------------------------- ...
- 爬虫(二)之scrapy框架
01-scrapy介绍 02-项目的目录结构: scrapy.cfg 项目的主配置信息.(真正爬虫相关的配置信息在settings.py 文件中) items.py 设置数据存储模板,用于结构化数据, ...
- Python—包介绍
包(Package) 当你的模块文件越来越多,就需要对模块文件进行划分,比如把负责跟数据库交互的都放一个文件夹,把与页面交互相关的放一个文件夹, . └── my_proj ├── crm #代码目录 ...
- Innodb 实现高并发、redo/undo MVCC原理
一.并发控制 因为并发情况下有可能出现不同线程对同一资源进行变动,所以必须要对并发进行控制以保证数据的同一与安全. 可以参考CPython解释器中的GIL全局解释器锁,所以说python中没有 ...
- hadoop和java 配置环境变量的的tar
第一步:打开工具上传tar包 如下图 第二步:在文件路径下查看是否上传成功 第三步:解压tar包 tar -zxvf hadoop.2.6.5.tar.gz 第四步:配置环 ...
- Servlet 快速概览
目录 生命周期 web.xml 获取表单数据(设置请求的编码格式) 返回响应内容(设置响应的编码格式) 结合前两点,总结基本模板 获取请求协议头部信息 设置响应头部信息 使用过滤器 在web.xml中 ...
- vue 开发依赖安装
安装element-ui yarn add element-ui --save 使用element-ui main.js import Vue from 'vue'; import ElementUI ...