CodeChef:Chef and Problems(分块)
题目大意
有一个长度为n的序列$a_1,a_2,……,a_n$,每次给出一个区间[l,r],求在区间内两个相等的数的最远距离($max(j-i,满足a_i==a_j且l\le i,j \le r)$)
思路:
分块将序列分成sqrt(n)块
预处理出每个数在每个块之后出现的最早位置和在每个块之前出现的最晚位置O(msqrt(n))
然后就可以按块进行区间DP,求出所有块之间的最大值 O(nsqrt(n))
答案就是max(f[L][R](两个数都在[L,R]里面的答案)O(1)
两个数都在[L,R]外面的答案,O(sqrt(n))
一个数在[L,R]里面,一个在外面的答案 O(sqrt(n)) )
总复杂度O(nsqrt(n))
具体实现看代码
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define maxn 100005
#define maxs 350
#define inf 0x3fffff
int block[maxn],a[maxn],size,f[maxs][maxs],pre[maxn][maxs],nex[maxn][maxs],mi[maxn];
int main(){
// freopen("1.in","r",stdin);
int n,m,q,l,r;scanf("%d%d%d",&n,&m,&q);size=sqrt(n);
for(int i=;i<=n;i++)scanf("%d",a+i),block[i]=(i-)/size+;
//预处理出每个数在每个块之后出现的最早位置和在每个块之前出现的最晚位置O(msqrt(n))
for(int i=;i<=n;i++)nex[a[i]][block[i]]=i;
for(int i=n;i>=;i--)pre[a[i]][block[i]]=i;
for(int i=;i<=m;i++){
pre[i][block[n]+]=inf;
for(int j=block[n];j>=;j--){
if(!pre[i][j])pre[i][j]=inf;
pre[i][j]=min(pre[i][j],pre[i][j+]);
}
for(int j=;j<=block[n];j++){
nex[i][j]=max(nex[i][j],nex[i][j-]);
}
}
//按块进行区间DP,求出所有块之间的最大值
for(int i=block[n];i>=;i--){
for(int j=i;j<=block[n];j++){
f[i][j]=max(f[i][j-],f[i+][j]);
for(int k=(i-)*size+,l=i*size;k<=l;k++){
f[i][j]=max(f[i][j],nex[a[k]][j]-k);
}
}
}
for(int i=;i<q;i++){
scanf("%d%d",&l,&r);
int L=block[l]+,R=block[r]-,ans=f[L][R];
//求出左端点在[L,R]外,右端点在[L,R]里面的答案
for(int j=l;block[j]==block[l];j++)if(!mi[a[j]])mi[a[j]]=j,ans=max(ans,nex[a[j]][R]-j);
for(int j=r;block[j]==block[r];j--){
ans=max(ans,j-(mi[a[j]]?mi[a[j]]:j));//求出两个端点都在[L,R]外的答案
ans=max(ans,j-pre[a[j]][L]);//求出右端点在[L,R]外,左端点在[L,R]里面的答案
}
for(int j=l;block[j]==block[l];j++)mi[a[j]]=;
printf("%d\n",ans);
}
return ;
}
CodeChef:Chef and Problems(分块)的更多相关文章
- CodeChef Chef and Churu [分块]
题意: 单点修改$a$ 询问$a$的区间和$f$的区间和 原来普通计算机是这道题改编的吧... 对$f$分块,预处理$c[i][j]$为块i中$a_j$出现几次,$O(NH(N))$,只要每个块差分加 ...
- codechef Chef and Problems
终于补出这道:一直耽搁到现在 找到一个代码可读性很好的分块temp; 题意:给一个长度为n 的数组 A,Q次询问,区间相等数的最大范围是多少? 数据范围都是10e5; 当然知道分块了: 传统分块看各种 ...
- Chef and Problems(from Code-Chef FNCS) ( 回 滚 )
题目: 题意:给定序列,求[l,r]区间内数字相同的数的最远距离. 链接:https://www.codechef.com/problems/QCHEF #include<bits/stdc++ ...
- 【xsy2111】 【CODECHEF】Chef and Churus 分块+树状数组
题目大意:给你一个长度为$n$的数列$a_i$,定义$f_i=\sum_{j=l_i}^{r_i} num_j$. 有$m$个操作: 操作1:询问一个区间$l,r$请你求出$\sum_{i=l}^{r ...
- 【Codechef-Hard】Chef and Churu 分块
题目链接: https://www.codechef.com/problems/FNCS Solution 大力分块.. 对序列分块,维护块内前缀和.块的前缀和,修改时暴力维护两个前缀和,询问单点答案 ...
- CODECHEF Chef and Churus 解题报告
[CODECHEF]Chef and Churus Description 有一个长度为\(n\)的数组\(A\),有\(n\)个函数,第\(i\)个函数的值为\(\sum_{j=l_i}^{r_i} ...
- Codechef TRIPS Children Trips (分块、倍增)
题目链接: https://www.codechef.com/problems/TRIPS 感觉CC有点毒瘤啊.. 题解: 首先有一个性质可能是因为太傻所以网上没人解释,然而我看了半天: 就是正序和倒 ...
- codechef Chef and The Right Triangles 题解
Chef and The Right Triangles The Chef is given a list of N triangles. Each triangle is identfied by ...
- codechef Chef And Easy Xor Queries
做法:我们考虑前缀异或和,修改操作就变成了区间[i,n]都异或x 查询操作就变成了:区间[1,x]中有几个k 显然的分块,每个块打一个tag标记表示这个块中所有的元素都异或了tag[x] 然后处理出这 ...
随机推荐
- colormap 参数及对应色卡
[参考] [1]matlab帮助文档
- js单线程
由于js是运行在单线程上的,所有浏览器单独开启一个线程来处理事件消息的轮询,避免阻塞js的执行.
- Arcmap中处理面图层中空白碎片
在面数据中,有时候在一个面要素中会出现碎片,而我们大多时候不希望这些碎片存在(图1),下面介绍通过Editor工具把这些碎片处理掉.
- 求一个n!中尾数有多少个零
题目描述: 输入一个正整数n,求n!(即阶乘)末尾有多少个0? 比如: n = 10; n! = 3628800,所以答案为2 输入描述: 输入为一行,n(1 ≤ n ≤ 1000) 输出描述: 输出 ...
- Java 11 发布计划来了,已确定 3个 新特性!!
Oracle 已经发布了 Java Development Kit 10,下一个版本 JDK 11 也在准备之中了.按照 Java 新的版本发布标准,Java 11 将在 6 个月后到来,现在它还只有 ...
- 我擦,DELPHI写个浏览器竟然这么容易,我只加了3个控件,写了3句代码。
- mysql on windows的安装
1.去官网下载合适的压缩包 网址:https://dev.mysql.com/downloads/file/?id=476233 (拉到最下面点击 No thanks,just start my do ...
- 下面分享一下RHEL/CentOS7 安装图形化桌面详细图解
Linux是一个多任务的多用户的操作系统,好多linux爱好者在安装完linux后经常遇到一个问题——没有图形化桌面(http://www.xcmnyy.com)今天小编在安装RHEL7的时候,一步留 ...
- 正则获取html标签字符串中图片地址
html标签字符串: var htmlStr = "<div class='testClass'><img=http://www.chinanews.com/part/ho ...
- 一个事件一定时间内只允许点击执行一次 与 vue阻止滚动穿透
可能我的方法很笨,简单实现来的就是给两个状态,一个状态点击时就发生改变,另外一个给一个定时器延迟改变 篮圈部分,给了两种状态,一个isDisable,一个comeTime 点击事件以后comeTime ...