博客
关于我
E - 买礼物(链表+线段树)
阅读量:323 次
发布时间:2019-03-04

本文共 2779 字,大约阅读时间需要 9 分钟。


题目大意

给出一个序列,有以下两种操作:

  • 1    x 1~~x 1  x:将位置 x x x上的数删除。
  • 2    l    r 2~~l~~r 2  l  r:若该区间内有两个相同的数输出 1 1 1否则输出 0 0 0

解题思路

很好的一道题,之前在洛谷写过查询区间内是否有两数相同是用莫队维护的区间种类数,但是本题如果写莫队估计要 T L E TLE TLE,然后学到了这手很强的问题转化技巧:

对于区间内的每个数,我们只需要知道它右边离他最近相同数的在哪个位置,然后判断区间内的最小值是否在区间内。(或者等价的,查询每个数左边相同数的位置最大值是否在区间内)。那么这时删除一个数,只需要像双向链表那样删除就行,因此需要两个数组 L , R L,R L,R分别记录每个数最左边和最右边相邻的数,需要注意链表首尾节点的删除要特判一下,删除节点就单点更新其最右边的相同的数为无穷。

#include 
#include
using namespace std;#define ENDL "\n"typedef long long ll;const int inf = 0x3f3f3f3f;const int maxn = 5e5 + 10;const int Mod = 1e9 + 7;int n;int a[maxn], L[maxn], R[maxn], pre[maxn * 2];int tree[maxn << 2];void build(int i, int l, int r) { if (l == r) { tree[i] = R[l]; return; } int mid = (l + r) >> 1, k = i << 1; build(k, l, mid); build(k | 1, mid + 1, r); tree[i] = min(tree[k], tree[k | 1]);}void change(int i, int l, int r, int pos, int x) { if (l == r) { tree[i] = x; return; } int mid = (l + r) >> 1, k = i << 1; if (pos <= mid) change(k, l, mid, pos, x); else change(k | 1, mid + 1, r, pos, x); tree[i] = min(tree[k], tree[k | 1]);}int query(int i, int l, int r, int x, int y) { if (l == x && r == y) return tree[i]; int mid = (l + r) >> 1, k = i << 1; if (y <= mid) return query(k, l, mid, x, y); else if (x > mid) return query(k | 1, mid + 1, r, x, y); else return min(query(k, l, mid, x, mid), query(k | 1, mid + 1, r, mid + 1, y));}int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int q, op, l, r; cin >> n >> q; memset(pre, 0x3f, sizeof pre); for (int i = 1; i <= n; i++) { cin >> a[i]; L[i] = pre[a[i]]; pre[a[i]] = i; } memset(pre, 0x3f, sizeof pre); for (int i = n; i >= 1; i--) R[i] = pre[a[i]], pre[a[i]] = i; //for (int i = 1; i <= n; i++) cout << L[i] << " "; cout << endl; //for (int i = 1; i <= n; i++) cout << R[i] << " "; cout << endl; build(1, 1, n); while (q--) { cin >> op; if (op == 1) { cin >> l; if (L[l] == inf) { if (R[l] != inf) { L[R[l]] = inf; } } else { if (R[l] == inf) { R[L[l]] = inf; change(1, 1, n, L[l], inf); } else { R[L[l]] = R[l]; L[R[l]] = L[l]; change(1, 1, n, L[l], R[l]); } } L[l] = R[l] = inf; change(1, 1, n, l, inf); } else { cin >> l >> r; int cur = query(1, 1, n, l, r); //cout << cur << " "; if (cur <= r) cout << "1" << endl; else cout << "0" << endl; } } return 0;}

转载地址:http://ppqq.baihongyu.com/

你可能感兴趣的文章
Linux下的系统监控与性能调优:从入门到精通
查看>>
LiveGBS user/save 逻辑缺陷漏洞复现(CNVD-2023-72138)
查看>>
localhost:5000在MacOS V12(蒙特利)中不可用
查看>>
logstash mysql 准实时同步到 elasticsearch
查看>>
Luogu2973:[USACO10HOL]赶小猪
查看>>
mabatis 中出现&lt; 以及&gt; 代表什么意思?
查看>>
Mac book pro打开docker出现The data couldn’t be read because it is missing
查看>>
MAC M1大数据0-1成神篇-25 hadoop高可用搭建
查看>>
mac mysql 进程_Mac平台下启动MySQL到完全终止MySQL----终端八步走
查看>>
Mac OS 12.0.1 如何安装柯美287打印机驱动,刷卡打印
查看>>
MangoDB4.0版本的安装与配置
查看>>
Manjaro 24.1 “Xahea” 发布!具有 KDE Plasma 6.1.5、GNOME 46 和最新的内核增强功能
查看>>
mapping文件目录生成修改
查看>>
MapReduce程序依赖的jar包
查看>>
mariadb multi-source replication(mariadb多主复制)
查看>>
MariaDB的简单使用
查看>>
MaterialForm对tab页进行隐藏
查看>>
Member var and Static var.
查看>>
memcached高速缓存学习笔记001---memcached介绍和安装以及基本使用
查看>>
memcached高速缓存学习笔记003---利用JAVA程序操作memcached crud操作
查看>>