HDU 4747 Mex (线段树)
来源:互联网 发布:软件开发入门书籍 编辑:程序博客网 时间:2024/06/14 07:41
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:给出一个序列,mex{}表示集合中没有出现的最小的自然数。然后 求sigma(mex (i , j)).
做法:考虑左端点固定时的所有区间的mex值,这个序列是一个非递减了。。。首先要明白。
初始就是求出mex[i]表示 mex(1 , i),对于每一个左端点,就是一个区间求和。
现在需要考虑的是左端点的改变对于序列的影响。。。
即左端点从i -> i + 1,mex[j]的改变。。。。即删去ai对于序列的影响。
如果 a[j] = a[i] 且 j > i ,不存在a[k] = a[i] j > k > i。即a[i]下一次出现的位置 。
根据mex的定义,我们知道 mex[k]不会改变, k >= j。因为删掉的ai还是存在于序列当中,所以不受影响。
之后需要考虑的是i +1 到 j - 1这段区间的mex值。。。删去了ai之后,使得原先mex值大于ai的,都会更新成ai。
很好理解。。。因为是没有出现的最小的,ai更小。。。
之前说过这是一个非递减的序列,所以原先mex值大于ai的也是一段连续的区间,所以我们可以找到最靠左的位置 r,使得mex[r] > a[i]。那么r 到 j - 1这段区间的mex值便 会更新为a[i]。
所以全部搞定。。。用线段树维护一下mex序列,区间更新,区间求和,然后一个查找就可以了。。。
#include <vector>#include <list>#include <map>#include <set>#include <queue>#include <deque>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <string>#include <cstring>using namespace std;typedef unsigned int UI;typedef long long LL;typedef unsigned long long ULL;typedef pair<int, int> PII;typedef vector<int> VI;typedef vector<bool> VB;typedef vector<char> VC;typedef vector<double> VD;typedef vector<string> VS;typedef vector<VI> VVI;typedef vector<PII> VPII;template <class T> inline void checkMin(T& a, T b) { if (b < a) a = b; }template <class T> inline void checkMax(T& a, T b) { if (b > a) a = b; }const int MOD = 1000000007;const int dx[] = {0, -1, 0, 1};const int dy[] = {1, 0, -1, 0};bool cmp(const PII& a, const PII& b) { if (a.first != b.first) return a.first < b.first; else return a.second < b.second;}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////const int N = 200010;PII b[N];int n, m, a[N], vis[N], next[N];#define lson step << 1#define rson step << 1 | 1struct Node { int left , right; int mx , lazy; LL sum; }L[N << 2];void pushUp (int step) { L[step].sum = L[lson].sum + L[rson].sum; L[step].mx = max (L[lson].mx , L[rson].mx);}void update (int step , int l , int r , int w) ;void pushDown (int step) { int l = L[step].left , r = L[step].right , m = (l + r) >> 1; int &z = L[step].lazy; if (z != -1) { update (lson , l , m , z); update (rson , m + 1 ,r , z); z = -1; }}void bulid (int step , int l , int r) { L[step].left = l; L[step].right = r; L[step].mx = L[step].sum = 0; L[step].lazy = -1; if (l == r) return ; int m = (l + r) >> 1; bulid (lson , l , m); bulid (rson , m + 1 , r);}void update (int step , int p , int w) { if (L[step].left == L[step].right) { L[step].mx = L[step].sum = w; return ; } pushDown (step); int m = (L[step].left + L[step].right) >> 1; if (p <= m) update (lson , p , w); else update (rson , p , w); pushUp (step);}void update (int step , int l , int r , int w) { if (L[step].left == l && L[step].right == r) { L[step].lazy = w; L[step].mx = w; L[step].sum = (r - l + 1) * 1LL * w; return ; } pushDown (step); int m = (L[step].left + L[step].right) >> 1; if (r <= m) update (lson , l , r , w); else if (l > m) update (rson , l , r , w); else { update (lson , l , m , w); update (rson , m + 1 , r , w); } pushUp (step);}int queryp (int step , int w) { if (L[step].mx <= w) return n + 1; if (L[step].left == L[step].right) return L[step].left; pushDown (step); int m = (L[step].left + L[step].right) >> 1; if (L[lson].mx > w) return queryp (lson , w); else return queryp (rson , w);}LL querys (int step , int l , int r) { if (L[step].left == l && L[step].right == r) return L[step].sum ; pushDown (step); int m = (L[step].left + L[step].right) >> 1; if (r <= m) return querys (lson , l , r); else if (l > m) return querys (rson , l , r); else return querys (lson , l , m) + querys (rson , m + 1 , r);}int main() { #ifndef ONLINE_JUDGE freopen ("input.txt" , "r" , stdin); // freopen ("output.txt" , "w" , stdout); #endif while (scanf("%d", &n) != EOF && n != 0) { for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); b[i] = make_pair(a[i], i); next[i] = n + 1; vis[i] = false; } vis[0] = false; sort(b + 1, b + n + 1, cmp); b[n + 1].first = b[n].first, b[n + 1].second = n + 1; for (int i = 1; i <= n; i++) { if (b[i + 1].first == b[i].first) next[b[i].second] = b[i + 1].second; } bulid (1 , 1 , n); int mmex = 0; for (int i = 1; i <= n; i++) { if (a[i] <= n) vis[a[i]] = true; while (vis[mmex]) mmex++; update(1 , i, mmex); } LL ans = 0; a[0] = n + 1; next[0] = n + 1; for (int l = 1; l <= n; l++) { if (a[l - 1] <= mmex) { int p0 = queryp(1 ,a[l - 1]); if (p0 != -1) p0 = max (p0, l); int p1 = next[l - 1]; if (p0 >= l && p0 < p1) update(1 ,p0 , p1 - 1 , a[l - 1]); } ans += querys(1 , l, n); } printf("%I64d\n", ans); } return 0
阅读全文
0 0
- [HDU 4747 Mex] 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 线段树
- HDU 4747 Mex (线段树)
- hdu 4747Mex【线段树】
- hdu 4747 Mex(线段树区间更新+二分)
- HDU 4747 Mex(线段树+思维题)
- hdu-4747-Mex-线段树区域更新
- Mex(线段树)
- HDU 4747 Mex (2013杭州网络赛1010题,线段树)★
- [bzoj3339]mex(线段树)
- NKOJ 4254 区间MEX (线段树)
- 链表中倒数第k个节点
- HDU 2222 Keywords Search(AC自动机模板)
- 重温python基础6:字典
- 傅里叶变换的通俗解释
- Scrapy: 爬虫返回403错误
- HDU 4747 Mex (线段树)
- 函数的返回值为指针类型的时候
- ThinkPHP3.2.3如何实现系统登录日志
- angular4+笔记
- 什么是值栈
- 字符串--Trie树(字典树)
- POJ 2778 DNA Sequence(AC自动机+矩阵快速幂)
- SPRING的体系结构
- 【Machine Learning】笔记:大数据下的机器学习