COJ 0985 WZJ的数据结构(负十五)(限定区域不同数)

传送门:http://oj.cnuschool.org.cn/oj/home/addSolution.htm?problemID=955

试题描述:

CHX有一个问题想问问大家。给你一个长度为N的数列A,请你找到两个位置L,R,使得A[L]、A[L+1]、……、A[R]中没有重复的数,输出R-L+1的最大值。

以上是附中联赛加试的一道题。WZJ觉得这道题太水了,改了改题目:

WZJ有一个问题想问问大家。给你一个长度为N的数列A,你要回答M次问题。每次问题给你两个正整数ql,qr。请你找到两个位置L、R (ql<=L<=R<=qr),使得A[L]、A[L+1]、……、A[R]中没有重复的数,输出R-L+1的最大值。

介于某些人的吐槽(不就是我嘛(⊙ ▽ ⊙)),本题不强制在线。注意范围,祝你好运!

输入:

输入第一行为两个正整数N,M。
输入第二行为N个整数Ai。
接下来M行每行两个正整数ql,qr。

输出:

对于每个问题,输出R-L+1的最大值。

输入示例:

5 3
1 2 1 3 4
1 3
2 4
2 5

输出示例:

2
3
4

其他说明:

1<=N<=200000
1<=M<=500000
1<=ql,qr<=N
-10^9<=Ai<=10^9

题解(幸好没有强制在线呀(⊙ ▽ ⊙))分治分成DP+RMQ。

我们先搞定最长不同数区间,每次来限制了就会把它砍断,对于右边的“此区间”我们预处理循环节计数再用RMQ搞定最大值,对于左区间我们二分找到编号,然后直接用L-ql出区间(这个区间一定没有重复数辣o(* ̄3 ̄)o)

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #define REP(i, s, n) for(int i = s; i <= n; i ++)
 7 #define RAP(i, n, s) for(int i = n; i >= s; i --)
 8 using namespace std;
 9 const int maxn = 200000 + 10;
10 const int maxhash = 871199;
11 int n, Q, d[maxn][20], Log[maxn], dp[maxn], A[maxn], last[maxn];
12 namespace HASH{
13     int fch[maxhash], next[maxn], val[maxn], ms = 0;
14     void hash_init() { memset(fch, -1, sizeof(fch)); }
15     int find_insert(int v){
16         int id = v % maxhash;
17         if(id < 0) id += maxhash;
18         for(int i = fch[id]; i != -1; i = next[i]) if(val[i] == v) return i;
19         next[ms] = fch[id]; val[ms] = v; return fch[id] = ms ++;
20     }
21 }using namespace HASH;
22 void RMQ(){
23     Log[0] = -1; REP(i, 1, n) d[i][0] = i - dp[i] + 1, Log[i] = Log[i >> 1] + 1;//此循环节开始计数了
24     for(int j = 1; (1 << j) <= n; j ++)
25         for(int i = 1; i + (1 << j) - 1 <= n; i ++)
26             d[i][j] = max(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
27     return ;
28 }
29 inline void read(int &x){
30     x = 0; int sig = 1; char ch = getchar();
31     while(!isdigit(ch)) { if(ch == ‘-‘) sig = -1; ch = getchar(); }
32     while(isdigit(ch)) x = 10 * x + ch - ‘0‘, ch = getchar();
33     x *= sig; return ;
34 }
35 inline void write(int x){
36     int len = 0, buf[10];
37     while(x) buf[++ len] = x % 10, x /= 10;
38     for(int i = len; i; i --) putchar(buf[i] + ‘0‘);
39     putchar(‘\n‘); return ;
40 }
41 void init(){
42     hash_init();
43     read(n); read(Q);
44     REP(i, 1, n) read(A[i]), A[i] = find_insert(A[i]), dp[i] = max(dp[i - 1], last[A[i]] + 1), last[A[i]] = i;
45     //更新循环节的尾巴,转移十分的机智啊我都想骂人了。最后别忘了更新自己的位置 (⊙ ▽ ⊙)
46     RMQ();
47     return ;
48 }
49 int query(int L, int R) {
50     int k = Log[R - L + 1];
51     return max(d[L][k], d[R - (1 << k) + 1][k]);
52 }
53 void work(){
54     int ql, qr;
55     while(Q --){
56         read(ql); read(qr);
57         int L = ql, R = qr + 1, M;
58         while(L + 1 < R){ //这二分什么鬼?ε=ε=ε=┏(゜ロ゜;)┛
59             M = L + R >> 1;
60             if(dp[M] < ql) L = M;//二分找循环节
61             else R = M ;//二分写错了?TAT
62         }
63         print(max(L - ql + 1, query(L + 1, qr)));//拆成两段,此循环节的前段和上一个循环节的后一段(ˉ﹃ˉ)
64     }
65     return ;
66 }
67 void print(){
68
69     return ;
70 }
71 int main(){
72     init();
73     work();
74     print();
75     return 0;
76 }
时间: 2024-10-13 06:03:02

COJ 0985 WZJ的数据结构(负十五)(限定区域不同数)的相关文章

COJ 1010 WZJ的数据结构(十) 线段树区间操作

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

COJ 1010 WZJ的数据结构(十) 线段树的地狱

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

15. 蛤蟆的数据结构进阶十五排序实现之堆排序

15. 蛤蟆的数据结构进阶十五排序实现之堆排序 本篇名言:"谁要是游戏人生 ,他就一事无成 ; 谁不能主宰自己 ,永远是一个奴隶.--歌德" 继续来看下堆排序. 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47733553 1.  堆排序 堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种.可以利用数组的特点快速定位指定索引的元素.堆分为大根堆和小根堆,是完全二叉树

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

COJ 0981 WZJ的数据结构(负十九)树综合

WZJ的数据结构(负十九) 难度级别:E: 运行时间限制:15000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 WZJ的数据结构中有很多都是关于树的.这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去: WZJ:为了大家简单,我规定一开始是一棵有根树. LZJ:那我一定得加上换根操作喽. XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做. CHX:子树信息修改,子树信息增加,子树

COJ 0995 WZJ的数据结构(负五)区间操作

WZJ的数据结构(负五) 难度级别:C: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行M次操作.操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数. 操作2:每次操作给你l,r,v三个参数,将Al至Ar中每个数的值+v. 输入 第一行为一个正整数N.第二行为N个整数Ai.第三行为一个正整数M.接下来M行每行4个正整数t,l,

COJ 0979 WZJ的数据结构(负二十一)

WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个N个点的图,初始状态无边. 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成树,输出“Not Yet”,否则输出当前最小生成树的权值. 输入 第一行两个正整数N,M.表示有N个点M个操作.接下来M行每行三个正整数u,v,w. 输出 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成

COJ 0999 WZJ的数据结构(负一)

WZJ的数据结构(负一) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 输入N个模板串Pi和文本串T,输出每个模板串Pi在T中出现了多少次. 输入 第一行为一个正整数N.接下来N行为Pi.最后一行为T 输出 输出N行,第i行为模板串Pi在T中出现的次数. 输入示例 5aabbaabaaababababa 输出示例 54445 其他说明 1<=sigma(|Pi|)<=10000001<=|T|<=10000

COJ 0967 WZJ的数据结构(负三十三)

WZJ的数据结构(负三十三) 难度级别:E: 运行时间限制:7000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行N次操作.操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数. 操作2:每次操作给你l,r,v三个参数,将Al至Ar所有数的值设为v. 输入 第一行为一个正整数N.第二行为N个整数Ai.接下来N行每行4个正整数t,l,r,v.若t=2表