[HDU 4747 Mex] Mex函数 线段树
来源:互联网 发布:潍坊行知2016升学率 编辑:程序博客网 时间:2024/06/08 09:55
·题目
http://acm.hdu.edu.cn/showproblem.php?pid=4747
·分析
先预处理出mex[1][i],记录每个位置下次出现的位置next[i],这里大于n的数都可以看作n+1
然后从前往后扫描,对于同一个i,容易发现mex[i][j]是随j递增的
于是找到i和next[i]-1之间第一个mex[i][j]比a[i]大的位置x
那么mex[i+1][x]到mex[i+1][next[i]-1]之间的值一定都为a[i],因为这一段a[i]空缺
于是转化为区间求和和区间赋值
·代码
/************************************************** * Problem: HDU 4747 * Author: clavichord93 * State: Accepted **************************************************/#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;typedef long long ll;const int MAX_N = 200005;int n;int a[MAX_N];int mex[MAX_N];int last[MAX_N];int next[MAX_N];ll sum[MAX_N << 2];int maxv[MAX_N << 2];int tag[MAX_N << 2];bool vis[MAX_N];#define lch(t) (t << 1)#define rch(t) (t << 1 | 1)void makeTree(int t, int l, int r) { if (l == r) { sum[t] = mex[l]; maxv[t] = mex[l]; tag[t] = -1; } else { int mid = (l + r) >> 1; makeTree(lch(t), l, mid); makeTree(rch(t), mid + 1, r); sum[t] = sum[lch(t)] + sum[rch(t)]; maxv[t] = max(maxv[lch(t)], maxv[rch(t)]); tag[t] = -1; }}void pushdown(int t, int l, int r) { if (tag[t] != -1) { int lt = lch(t); int rt = rch(t); int mid = (l + r) >> 1; sum[lt] = tag[t] * (mid - l + 1); maxv[lt] = tag[t]; tag[lt] = tag[t]; sum[rt] = tag[t] * (r - mid); maxv[rt] = tag[t]; tag[rt] = tag[t]; tag[t] = -1; }}ll getSum(int t, int l, int r, int x, int y) { if (x <= l && r <= y) { return sum[t]; } else { pushdown(t, l, r); int mid = (l + r) >> 1; ll sum = 0; if (x <= mid) { sum += getSum(lch(t), l, mid, x, y); } if (y > mid) { sum += getSum(rch(t), mid + 1, r, x, y); } return sum; }}int getPos(int t, int l, int r, int x, int y, int val) { if (l == r) { return l; } else { pushdown(t, l, r); int mid = (l + r) >> 1; if (x <= mid && maxv[lch(t)] > val) { return getPos(lch(t), l, mid, x, y, val); } if (y > mid && maxv[rch(t)] > val) { return getPos(rch(t), mid +1, r, x, y, val); } return -1; }}void change(int t, int l, int r, int x, int y, int val) { if (x <= l && r <= y) { tag[t] = val; sum[t] = (ll)(r - l + 1) * val; maxv[t] = val; } else { pushdown(t, l, r); int mid = (l + r) >> 1; if (x <= mid) { change(lch(t), l, mid, x, y, val); } if (y > mid) { change(rch(t), mid + 1, r, x, y, val); } sum[t] = sum[lch(t)] + sum[rch(t)]; maxv[t] = max(maxv[lch(t)], maxv[rch(t)]); }}#undef lch#undef rchint main() { #ifdef LOCAL_JUDGE freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif while (scanf("%d", &n), n) { for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); if (a[i] > n) { a[i] = n + 1; } } for (int i = 0; i <= n + 1; i++) { last[i] = n + 1; vis[i] = 0; } for (int i = n; i >= 1; i--) { next[i] = last[a[i]]; last[a[i]] = i; } int last = 0; for (int i = 1; i <= n; i++) { vis[a[i]] = 1; while (vis[last]) { last++; } mex[i] = last; } //for (int i = 1; i <= n; i++) { //printf("%d ", mex[i]); //} //printf("\n"); makeTree(1, 1, n); ll ans = 0; for (int i = 1; i <= n; i++) { ans += getSum(1, 1, n, i, n); int x = getPos(1, 1, n, i, next[i] - 1, a[i]); //cout << "Ans = " << ans << endl; //cout << "Pos = " << x << endl; //cout << "Next = " << next[i] << endl; //cout << "A[i] = " << a[i] << endl; //cout << endl; if (1 <= x && x <= next[i] - 1) { change(1, 1, n, x, next[i] - 1, a[i]); } } printf("%I64d\n", ans); } return 0;}
0 0
- [HDU 4747 Mex] Mex函数 线段树
- hdu 4747 Mex (线段树)
- hdu 4747 Mex 线段树
- HDU 4747 Mex (线段树)
- hdu 4747Mex【线段树】
- HDU 4747 Mex (线段树)
- hdu - 4747 - Mex(二分+线段树)
- hdu 4747 Mex(线段树)
- hdu 4747 Mex(线段树)
- hdu-4747-Mex-线段树区域更新
- HDU 4747 Mex (线段树)
- HDU 4747 Mex (线段树)
- hdu 4747 Mex(线段树区间更新+二分)
- HDU 4747 Mex(线段树+思维题)
- 区间MEX 线段树维护mex数组
- hdu4747 mex 线段树
- Mex(线段树)
- hdu 4747 Mex
- 编译自己的 Code::Blocks ! (三)为 Code::Blocks 编译一个专用 wxWidgets 2.8.12 库
- 关于Java中变量初始化问题
- 我的COM和ATL的学习
- 我的QML学习笔记-前言
- C++字符串转化为数字的库函数
- [HDU 4747 Mex] Mex函数 线段树
- iOS解析---WebView和js交互原理
- matlab rand函数详解
- ActivityGroup基本菜单的实现和弹出菜单的实现
- 交换机和路由器分别的实现原理是什么?分别在哪个层次上面实现的?
- mysql 5.6 免安装,启动的时候存在的问题
- 程序员面试简历注意事项
- 面向对象编程的弊端
- 黑马程序员-----Hello Word!!