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掉. 观察要求的东西发现我们只关系一行的答案. ...
随机推荐
- python:实例化configparser模块读写配置文件
之前的博客介绍过利用python的configparser模块读写配置文件的基础用法,这篇博客,介绍下如何实例化,方便作为公共类调用. 实例化的好处有很多,既方便调用,又降低了脚本的维护成本,而且提高 ...
- ASP.NET Core MVC – Tag Helpers 介绍
ASP.NET Core Tag Helpers系列目录,这是第一篇,共五篇: ASP.NET Core MVC – Tag Helpers 介绍 ASP.NET Core MVC – Caching ...
- 卷积神经网络CNN的意义
一.选用卷积的原因 局部感知 简单来说,卷积核的大小一般小于输入图像的大小(如果等于则是全连接),因此卷积提取出的特征会更多地关注局部 —— 这很符合日常我们接触到的图像处理.而每个神经元其实没有必要 ...
- logstash安装及基础入门
Logstash是一款开源的数据收集引擎,具备实时管道处理能力.简单来说,logstash作为数据源与数据存储分析工具之间的桥梁,结合 ElasticSearch以及Kibana,能够极大方便数据的处 ...
- portscaner 多线程、多协程并发端口扫描
import socket,time,re,sys,os,threading import gevent from gevent import monkey monkey.patch_all() so ...
- docker之导出、导入、数据搬迁
docker 导出 导入有二种,一种是备份镜像,一种备份容器.数据搬迁,最简单粗暴就是直接COPY,volume的路径就行了. 一.导出导入镜像 #导出为tar docker save #ID or ...
- git的用法步骤讲解
1.创建全局的本地用户名 git config --global user.name "teamemory" git config --global user.email &quo ...
- C#对摄像头的操作示例,采用Aforge库
操作摄像头有三个办法:VFW.DirectShow.花钱买第三方控件 VFW技术比较古老,无法解决驱动不完善造成的某些问题 DirectShow技术相对完善一些,但这是C++才能实现的技术.如果用.N ...
- 同步和异步概念(由DZW前端框架引发的百度地图api无法加载问题总结)
首先概念: 在计算机领域,同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去:异步是指进程不需要一直等下去,而是继续 ...
- 项目集成自动分词系统ansj,实现自定义词库
一,分词系统地址:https://github.com/NLPchina/ansj_seg 二,为什么选择ansj? 1.项目需求: 我们平台要做手机售后的舆情分析,即对购买手机的用户的评论进行分析. ...