Violet 6 杯省选模拟赛 蒲公英
https://www.luogu.com.cn/problem/P4168
题目
给$n$个数字,有$m$次询问,问$a_l, a_{l+1} , \dots , a_r$的众数是什么,
$1\leqslant n \leqslant 40000, 1\leqslant m \leqslant 50000, 1\leqslant a_i\leqslant10^9$
题解
第一次做分块
方法一
因为n不是很大,所以可以对数据进行离散化后统计出现次数
所以就可以直接统计最大的了。这样复杂度是$\mathcal{O}(m\times n)$,肯定超时
可以尝试提前分块打出一些表,比如分成$t$块,然后提前打好$\binom{t}{2}$块的最大值,并保存是哪一个
那么每次查询的时候最多花$2\times \lfloor n/t\rfloor$的时间,时间复杂度是$\mathcal{O}(t^2n+2mn/t)$
把$m$和$n$看作同数量级,设为N,那么得到$t^2N+2N^2/t$,为了保证数量级相同,设$t^2N=2N^2/t$,得到$t=\sqrt[3]{N}$
因为大于或小于以后两边渐进复杂度都会增加,导致整个表达式的渐进复杂度增加(算法导论:证明$max(a,b)=\Theta(a+b)$)
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
#define REP(i,a,b) for(register int i=(a); i<(b); i++)
#define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
#define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) void(0)
#endif
typedef long long ll;
#define MAXN 40007
#define MAXM 50007
#define MAXD 35
int a[MAXN], b[MAXN], c[MAXN];
int d[MAXD][MAXD][MAXN];
int now[MAXN];
int t,l,na;
int x=0;
inline void did(int f) {
now[f]++;
if(now[na]<now[f] || (now[na]==now[f] && now[na+1]>f)) {
now[na+1]=f;
now[na]=now[f];
}
}
inline int go(int z, int y) {
int i=(z+l-1)/l, j=y/l;
int L=i*l, R=j*l;
if(i<j) {
REP(k,0,na+2)
now[k] = d[i][j][k];
REP(f,z,L) did(c[f]);
REP(f,R,y) did(c[f]);
} else {
memset(now,0,sizeof now);
REP(f,z,y) did(c[f]);
}
return x=b[now[na+1]];
}
int main() {
int n,m; scanf("%d%d", &n, &m);
REP(i,0,n) {scanf("%d", &a[i]); b[i]=a[i];}
sort(b,b+n); na = unique(b,b+n)-b;
REP(i,0,n) {
c[i] = lower_bound(b,b+na,a[i])-b;
}
memset(d,0,sizeof d);
t = pow((double)n, (double)1/3);
l = t ? n/t : n;
REP(i,0,t) REPE(j,i,t) {
REP(f,i*l,j*l) {
int k = c[f];// DBG("*%d\n", k);
d[i][j][k]++;
if(d[i][j][k]>d[i][j][na] || (d[i][j][k]==d[i][j][na] && k<d[i][j][na+1])) {
d[i][j][na] = d[i][j][k];
d[i][j][na+1] = k;
}
}
} REP(i,0,m) {
int l0, r0;
scanf("%d%d", &l0, &r0);
int l = (l0 + x - 1) % n + 1;
int r = (r0 + x - 1) % n + 1;
if(l>r) swap(l,r);
go(l-1,r);
printf("%d\n", x);
}
return 0;
}
方法二
用同样的分块方法,但是只记录最大值,不记录次数,而使用二分确定大小,一次二分确定大小需要$\mathcal{O}(\log n)$。
设需要分$D$块,然后得到时间复杂度$\mathcal{O}(D\times N+2MN/D\log n)$(因为剩下部分最长是两个块,虽然比平均情况大,但是为了应付数据,数据是最大的很多……)
那么用相同的方法,解得$D=\sqrt{2N\log N}$
中间有个细节,就是计算D和L的时候要考虑是偏大还是篇小,由于我快断电了,所以坑了
AC代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<cassert>
using namespace std;
#define REP(i,a,b) for(register int i=(a); i<(b); i++)
#define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
#define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__)
#else
#define DBG(...) void(0)
#endif
typedef long long ll;
#define MAXN 50007
#define MAXM 50007
#define MAXL 1007
#define MAXD 884*2
int a[MAXN],b[MAXN],c[MAXN],nb;
int fk[MAXD][MAXD], L, D;
int cnt[MAXN], nmax, ncnt;
int x=0;
vector<int> arr[MAXN];
int calc(int l, int r, int b) {
//r--;
return lower_bound(arr[b].begin(), arr[b].end(), r)-lower_bound(arr[b].begin(), arr[b].end(), l);
}
void did(int l, int r, int b) {
int t=calc(l,r,b);
if(t>ncnt || (t==ncnt && b<nmax)) {
ncnt=t;
nmax=b;
}
}
void work(int l, int r) {
nmax=0, ncnt=0;
int z=(l+L-1)/L, y=r/L;
if(z<y) {
int Z=z*L, Y=y*L;
REP(i,l,Z) did(l,r,c[i]);
REP(i,Y,r) did(l,r,c[i]);
did(l,r,fk[z][y]);
} else {
REP(i,l,r) did(l,r,c[i]);
}
x=b[nmax];
}
int main() {
int n,m; scanf("%d%d", &n, &m);
REP(i,0,n) {
scanf("%d", &a[i]);
b[i]=a[i];
}
sort(b,b+n);
nb = unique(b,b+n)-b;
REP(i,0,n) {
c[i] = lower_bound(b,b+nb,a[i])-b;
}
D = sqrt(log((double)n)/log(2.0)*n*2); if(D==0) D=1;
L = n/D; //L<L' D>D'
D = n/L; //L>L' D<D'
REP(i,0,D) {
int s=i*L;
nmax = 0, ncnt = 0;
REP(k,0,n) cnt[k]=0;
REP(j,s,n) {
int J=(j+1+L-1)/L, k=c[j];
cnt[k]++;
if(cnt[k]>ncnt ||(cnt[k]==ncnt && k<nmax)) {
ncnt = cnt[k];
nmax = k;
}
fk[i][J]=nmax;
}
}
REP(i,0,n) {
arr[c[i]].push_back(i);
}
REP(i,0,m) {
int l,r;
scanf("%d%d", &l, &r);
l = (l+x-1)%n+1, r=(r+x-1)%n+1;
if(l>r) swap(l,r);
work(l-1,r);
printf("%d\n", x);
}
}
Violet 6 杯省选模拟赛 蒲公英的更多相关文章
- Contest Hunter Round #70 - 连续两大交易事件杯省选模拟赛
orz lydrainbowcat [Problem A]「艦これ市」70万幕后交易事件 排序机器=-=.重要的是相同的处理. 我们可以从小到大添加数字,然后维护一个位置的序列.每一种相等的数字都在一 ...
- codehunter 「Adera 6」杯省选模拟赛 网络升级 【树形dp】
直接抄ppt好了--来自lyd 注意只用对根判断是否哟留下儿子 #include<iostream> #include<cstdio> using namespace std; ...
- 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解
今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...
- @省选模拟赛03/16 - T3@ 超级树
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...
- 3.28 省选模拟赛 染色 LCT+线段树
发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...
- 省选模拟赛第四轮 B——O(n^4)->O(n^3)->O(n^2)
一 稍微转化一下,就是找所有和原树差距不超过k的不同构树的个数 一个挺trick的想法是: 由于矩阵树定理的行列式的值是把邻接矩阵数值看做边权的图的所有生成树的边权乘积之和 那么如果把不存在于原树中的 ...
- NOI2019省选模拟赛 第五场
爆炸了QAQ 传送门 \(A\) \(Mas\)的童年 这题我怎么感觉好像做过--我记得那个时候还因为没有取\(min\)结果\(100\to 0\)-- 因为是个异或我们肯定得按位考虑贡献了 把\( ...
- NOI2019省选模拟赛 第六场
传送门 又炸了-- \(A\) 唐时月夜 不知道改了什么东西之后就\(A\)掉了\(.jpg\) 首先,题目保证"如果一片子水域曾经被操作过,那么在之后的施法中,这片子水域也一定会被操作&q ...
- 省选模拟赛 arg
1 arg (arg.cpp/in/out, 1s, 512MB)1.1 Description给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. ...
随机推荐
- Django forms组件与钩子函数
目录 一.多对多的三种创建方式 1. 全自动 2. 纯手撸(了解) 3. 半自动(强烈推荐) 二.forms组件 1. 如何使用forms组件 2. 使用forms组件校验数据 3. 使用forms组 ...
- IIS配置svc(IIS8中添加WCF支持几种方法小结)
方法一 最近在做Silverlight,Windows Phone应用移植到Windows 8平台,在IIS8中测试一些传统WCF服务应用,发现IIS8不支持WCF服务svc请求,后来发现IIS8缺少 ...
- Vue与Django前后台分离跨域配置
一.跨域: 简单来说:如果前端向后端请求数据,前后端的的ip和端口都是不一致的,就是不在统一域名下,就出现了CORS跨域问题. 二.后台处理跨域 在django后台环境目录下安装插件: >: p ...
- 2、手写Unity容器--第一层依赖注入
这个场景跟<手写Unity容器--极致简陋版Unity容器>不同,这里构造AndroidPhone的时候,AndroidPhone依赖于1个IPad 1.IPhone接口 namespac ...
- JDK1.8新特性-Lambda表达式
Lambda 表达式 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性. Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中). 使用 Lambda 表 ...
- DG中switchover切换操作
问题描述:我们配置DG的目的就是为了在主库出现故障时,备库能够提供服务,保证业务的正常运行,switchover是用户有计划的进行停机切换,能够保证不丢失数据,我记录一下我进行switchover中的 ...
- uiautomatorviewer提示Unable to connect to adb. Check if adb is installed correctly解决方法
转自:https://www.jianshu.com/p/c8581a70d1bc 解决方案: 1.打开 "E:\android-sdk_r24.4.1-windows\android-s ...
- Leetcode327: Count of Range Sum 范围和个数问题
###问题描述 给定一个整数数组,返回range sum 落在给定区间[lower, upper] (包含lower和upper)的个数.range sum S(i, j) 表示数组中第i 个元素到j ...
- 封装和@property
封装和@property 一.复习 1.接口类和抽象类 python中没有接口类,有抽象类,abc模块中的metaclass=ABCMeta,@abstructmethod,本质是做代码规范用的,希望 ...
- jQuery-验证码倒计时的实现
点击发送验证码,通常需要加入倒计时功能,HTML如下: <center class='block captchaArea'> <input class="input pwd ...