51Nod-1571-最近等对
2017-07-30 02:48
204 查看
ACM模版
区间更新,区间查询,注意延迟标记。
描述
题解
挺常见的一种线段树问题,首先对 a[] 进行离散化,然后询问离线处理,处理时需要根据右区间进行排序,然后不断维护左区间就好了……每次添加离散化后的 a[i] 时都要处理完询问中右区间端点为 i 的查询,避免后续添加对它的影响。区间更新,区间查询,注意延迟标记。
代码
#include <iostream> #include <cstdio> #include <algorithm> #define lson rt << 1 #define rson rt << 1 | 1 using namespace std; const int MAXN = 5e5 + 10; const int INF = 0x3f3f3f3f; struct node { int l, r, id; } q[MAXN]; // 查询 int n, m; int a[MAXN]; int b[MAXN]; int pre[MAXN]; int ans[MAXN]; int minv[MAXN << 2]; int lazy[MAXN << 2]; int cmp(node a, node b) { return a.r < b.r; } void build(int rt, int l, int r) { minv[rt] = n, lazy[rt] = INF; if (l == r) { return ; } int m = (l + r) >> 1; build(lson, l, m); build(rson, m + 1, r); } void pushup(int rt) { minv[rt] = min(minv[lson], minv[rson]); } void pushdown(int rt) { if (lazy[rt] != INF) { minv[lson] = min(minv[lson], lazy[rt]); minv[rson] = min(minv[rson], lazy[rt]); lazy[lson] = min(lazy[lson], lazy[rt]); lazy[rson] = min(lazy[rson], lazy[rt]); lazy[rt] = INF; } } void update(int rt, int l, int r, int l_, int r_, int v) { if (l_ <= l && r_ >= r) { minv[rt] = min(minv[rt], v); lazy[rt] = min(lazy[rt], v); return ; } pushdown(rt); int m = (l + r) >> 1; if (l_ <= m) { update(lson, l, m, l_, r_, v); } if (r_ > m) { update(rson, m + 1, r, l_, r_, v); } pushup(rt); } int query(int rt, int l, int r, int l_, int r_) { if (l_ <= l && r_ >= r) { return minv[rt]; } pushdown(rt); int ans = INF, m = (l + r) >> 1; if (l_ <= m) { ans = min(ans, query(lson, l, m, l_, r_)); } if (r_ > m) { ans = min(ans, query(rson, m + 1, r, l_, r_)); } pushup(rt); return ans; } void slove() { build(1, 1, n); for (int i = 1; i <= n; i++) { pre[i] = n; } for (int i = 1, j = 1; i <= n && j <= m; i++) { if (pre[a[i]] == n) // 记录离散化后的 a[i] 的前一个位置 { pre[a[i]] = i; } else { update(1, 1, n, 1, pre[a[i]], i - pre[a[i]]); pre[a[i]] = i; } while (j <= m && q[j].r == i) { ans[q[j].id] = query(1, 1, n, q[j].l, n); j++; } } } template <class T> inline bool scan_d(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) { return 0; //EOF } while (c != '-' && (c < '0' || c > '9')) { c = getchar(); } sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0' && c <= '9') { ret = ret * 10 + (c - '0'); } ret *= sgn; return 1; }
相关文章推荐
- 51nod 1571 最近等对 | 线段树 离线
- 最近很烦!
- 只想说说最近的生活
- 第一篇博客文章,发表试试。最近新看到的两道比较有意思的数据结构题
- 51Nod-1500-苹果曼和树
- 最近出现很多数据库被攻击案例,在数据库中的文本型字段中加入了script代码
- 最近不知道记录写什么
- 51nod 1682 中位数计数
- 51Nod-1090 3个数和为0【排序+二分查找】
- 最近开了一个论坛
- 最近到手的一些书
- 51nod 1276 岛屿的数量
- 51Nod - 1453 抽彩球 逆推+排列组合
- 51nod 1859 Clarke and number ACM
- 更改Visual Studio“最近的项目”列表的程序编程
- 关于SAE本地环境最近更新后mysql_connect未定义问题
- 51Nod-1333-无聊的数学家们
- 51Nod 1006 最长公共子序列Lcs问题 模板题
- 51Nod-1029-大数除法
- 也说《最近辞退了一个实习生,心情好了很多,差点儿犯了曾有过的同样的错误,趁早让你走人一切就正确了》