传送门

这个题的方法好像很多啊

1.莫队暴力

2.线段树 + 离线处理

先预处理出sg[i]表示前i个数的sg值,next[i]表示i的下一位置在哪里,如果后面再没有i,那么next[i] = n + 1

然后把线段树的每个叶子节点放上sg[i]。

把询问按照左端点由小到大排序,我们考虑如何从 l ~ r 转移到 l + 1 ~ r,

会发现,当把a[l]这个数去掉之后,如果后面没有a[l]那么答案就可能会更新,

那么我们可以更新 l + 1 ~ next[l] - 1这个区间,也就是用线段树操作

#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 200001
#define INF ~(1 << 31)
#define root 1, 1, n
#define ls now << 1, l, mid
#define rs now << 1 | 1, mid + 1, r
#define min(x, y) ((x) < (y) ? (x) : (y)) int n, q;
int a[N], next[N], vis[N], ans[N], mx[N << 2], sg[N]; struct node
{
int x, y, id;
}p[N]; inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
return x * f;
} inline bool cmp(node x, node y)
{
return x.x < y.x;
} inline void build(int now, int l, int r)
{
if(l == r)
{
mx[now] = sg[l];
return;
}
mx[now] = INF;
int mid = (l + r) >> 1;
build(ls);
build(rs);
} inline void push_down(int now)
{
if(mx[now] != INF)
{
mx[now << 1] = min(mx[now << 1], mx[now]);
mx[now << 1 | 1] = min(mx[now << 1 | 1], mx[now]);
mx[now] = INF;
}
} inline void update(int now, int l, int r, int x, int y, int d)
{
if(x <= l && r <= y)
{
mx[now] = min(mx[now], d);
return;
}
push_down(now);
int mid = (l + r) >> 1;
if(x <= mid) update(ls, x, y, d);
if(mid < y) update(rs, x, y, d);
} inline int query(int now, int l, int r, int x)
{
if(l == r) return mx[now];
push_down(now);
int mid = (l + r) >> 1;
if(x <= mid) return query(ls, x);
else return query(rs, x);
} int main()
{
int i, j = 0, now = 1, nxt;
n = read();
q = read();
for(i = 1; i <= n; i++) a[i] = read();
for(i = 1; i <= n; i++)
{
vis[a[i]] = 1;
while(vis[j]) j++;
sg[i] = j;
}
build(root);
for(i = 0; i <= n; i++) vis[i] = n + 1;
for(i = n; i >= 1; i--) next[i] = vis[a[i]], vis[a[i]] = i;
for(i = 1; i <= q; i++)
{
p[i].id = i;
p[i].x = read();
p[i].y = read();
}
std::sort(p + 1, p + q + 1, cmp);
for(i = 1; i <= q; i++)
{
while(now < p[i].x)
{
if(now + 1 < next[now])
update(root, now + 1, next[now] - 1, a[now]);
now++;
}
ans[p[i].id] = query(root, p[i].y);
}
for(i = 1; i <= q; i++) printf("%d\n", ans[i]);
return 0;
}

3.主席树

。。不会

[BZOJ3339] Rmq Problem(线段树)的更多相关文章

  1. Codeforces 803G Periodic RMQ Problem 线段树

    Periodic RMQ Problem 动态开点线段树直接搞, 我把它分成两部分, 一部分是原来树上的, 一部分是后来染上去的,两个部分取最小值. 感觉有点难写.. #include<bits ...

  2. bzoj 3489 A simple rmq problem - 线段树

    Description 因为是OJ上的题,就简单点好了.给出一个长度为n的序列,给出M个询问:在[l,r]之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大.如果找不到这样的数,则直 ...

  3. [bzoj3339]Rmq Problem||[bzoj3585]mex_线段树

    Rmq Problem bzoj-3339||mex bzoj-3585 题目大意:给定一个长度为n的数列a,多次讯问区间l,r中最小的不属于集合{$A_l,A_{l+1}...A_r$}的非负整数. ...

  4. bzoj 3489 A simple rmq problem——主席树套线段树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3489 题解:http://www.itdaan.com/blog/2017/11/24/9b ...

  5. BZOJ3339 Rmq Problem

    [bzoj3339]Rmq Problem Description Input Output Sample Input 7 5 0 2 1 0 1 3 2 1 3 2 3 1 4 3 6 2 7 Sa ...

  6. bzoj 3489: A simple rmq problem k-d树思想大暴力

    3489: A simple rmq problem Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 551  Solved: 170[Submit][ ...

  7. Codeforces Round #271 (Div. 2) F. Ant colony (RMQ or 线段树)

    题目链接:http://codeforces.com/contest/474/problem/F 题意简而言之就是问你区间l到r之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数 ...

  8. 【题解】BZOJ3489 A Hard RMQ problem(主席树套主席树)

    [题解]A simple RMQ problem 占坑,免得咕咕咕了,争取在2h内写出代码 upd:由于博主太菜而且硬是要用指针写两个主席树,所以延后2hQAQ upd:由于博主太菜而且太懒所以他决定 ...

  9. Uva 12299 带循环移动的RMQ(线段树)

    题目链接:https://vjudge.net/contest/147973#problem/C 题意:传统的RMQ是一个不变的数组a求区间最值.现在要循环移动(往前移动). 分析:求区间问题,很容易 ...

随机推荐

  1. 【2016新年版】年度精品 XP,32/64位Win7,32/64位Win8,32/64位Win10系统

    本系统是10月5日最新完整版本的Windows10 安装版镜像,win10正式版,更新了重要补丁,提升应用加载速度,微软和百度今天宣布达成合作,百度成为win10 Edge浏览器中国默认主页和搜索引擎 ...

  2. FZU 1977 Pandora adventure (插头DP,常规)

    题意:有一个n*m矩阵,其中有些格子必走,有些格子不可走,其他格子是可走也可不走,问有多少条哈密顿回路? 思路: 本来是一道很简单的题,代码写多了连白痴bug都查不出了,竟然用i>=ex& ...

  3. Web开发者必须知道的10个jQuery代码片段

    在过去的几年中,jQuery一直是使用最为广泛的JavaScript脚本库.今天我们将为各位Web开发者提供10个最实用的jQuery代码片段,有需要的开发者可以保存起来. 1.检测Internet ...

  4. CPP-基础:关于引用

    1.什么是“引用”?申明和使用“引用”要注意哪些问题? 引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同. 申明一个引用的时候,切记要对其进行初始化. 引用声明完 ...

  5. Codeforces Round #273 (Div. 2)-C. Table Decorations

    http://codeforces.com/contest/478/problem/C C. Table Decorations time limit per test 1 second memory ...

  6. C语言中函数参数传递

    C语言中函数参数传递的三种方式 (1)值传递,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值.(2)地址传递,就是把 ...

  7. 美可能排除中国大陆制造/生产的所有5G产品

    https://www.wsj.com/articles/u-s-considers-requiring-5g-equipment-for-domestic-use-be-made-outside-c ...

  8. PAT (Basic Level) Practise (中文)-1038. 统计同成绩学生(20)

    PAT (Basic Level) Practise (中文)-1038. 统计同成绩学生(20)    http://www.patest.cn/contests/pat-b-practise/10 ...

  9. java常考小程序

    private static void nineNineMulitTable(){ /** * 9*9乘法表 */ for (int i = 1,j = 1; j <= 9; i++) { Sy ...

  10. ios调试小结

    Xcode底部的小黑盒是我们调试时的好朋友,它可以输出日志信息.错误信息以及其他有用的东西来帮你跟踪错误,除了可以看到日志直接输出的信息外,我们编程过程中也可以在某些断点停留,来检查app的多个方面. ...