博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[2013 ACM/ICPC Asia Regional Hangzhou Online J/1010]hdu 4747 Mex (线段树)
阅读量:5222 次
发布时间:2019-06-14

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

题意:

给定一个长度为 n 的非负数列,定义 mex(l, r) 为 l,r 区间里最小的没有出现的数字。

求所有 mex(l, r) 的和

分析参见 

我的代码:

ExpandedBlockStart.gif
  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <vector>
  5 typedef 
long 
long ll;
  6 
#define lson l, mid, rt << 1
  7 
#define rson mid + 1, r, rt << 1 |1
  8 
  9 
struct node {
 10     
int mx, mi, setv;
 11     ll sum;
 12 };
 13 
 14 
const 
int N = 
200000 + 
10;
 15 
int ar[N];
 16 node seg[N << 
2];
 17 
 18 
bool vis[N];
 19 
int idx;
 20 
 21 
void Up(node& fa, node& ls, node& rs) {
 22     fa.mx = std::max(ls.mx , rs.mx);
 23     fa.sum = ls.sum + rs.sum;
 24     fa.mi = std::min(ls.mi, rs.mi);
 25 }
 26 
void build(
int l, 
int r, 
int rt) {
 27     seg[rt].setv = -
1;
 28     
if (l == r) {
 29         vis[ar[l]] = 
true;
 30         
while (vis[idx])
 31             ++idx;
 32         seg[rt].mx = seg[rt].mi = seg[rt].sum = idx;
 33     } 
else {
 34         
int mid = (l + r) >> 
1;
 35         build(lson);
 36         build(rson);
 37         Up(seg[rt], seg[rt << 
1], seg[rt << 
1 | 
1]);
 38     }
 39 }
 40 
void Down(node& fa, node& ls, node& rs, 
int len) {
 41     
if (~fa.setv) {
 42         ls.setv = rs.setv = ls.mx = rs.mx = ls.mi = rs.mi = fa.setv;
 43         ls.sum = (ll)(len - (len >> 
1)) * fa.setv;
 44         rs.sum = (ll)(len >> 
1) * fa.setv;
 45         fa.setv = -
1;
 46     }
 47 }
 48 ll query(
int L, 
int R, 
int l, 
int r, 
int rt) {
 49     
if (L == l && R == r)
 50         
return seg[rt].sum;
 51     Down(seg[rt], seg[rt << 
1], seg[rt << 
1 | 
1], r - l + 
1);
 52     
int mid = (l + r) >> 
1;
 53     
if (R <= mid) 
return query(L, R, lson);
 54     
else 
if (L > mid) 
return query(L, R, rson);
 55     
else 
return query(L, mid, lson) + query(mid + 
1, R, rson);
 56 }
 57 
void update(
int L, 
int R, 
int v, 
int l, 
int r, 
int rt) {
 58     
if (seg[rt].mx <= v) 
return ;
 59     
int mid = (l + r) >> 
1;
 60     
if (L == l && R == r) {
 61         
if (seg[rt].mi >= v) {
 62             seg[rt].mi = seg[rt].mx = seg[rt].setv = v;
 63             seg[rt].sum = (ll)(r - l + 
1) * v;
 64             
return ;
 65         }
 66         
if (l == r) {
 67             
if (seg[rt].mx > v) {
 68                 seg[rt].mi = seg[rt].mx = seg[rt].sum = v;
 69                 seg[rt].setv = -
1;
 70             }
 71             
return ;
 72         }
 73         
//
 74 
        Down(seg[rt], seg[rt << 
1], seg[rt << 
1 | 
1], r - l + 
1);
 75         
if (R <= mid) update(L, R, v, lson);
 76         
else 
if (L > mid) update(L, R, v, rson);
 77         
else {
 78             update(L, mid, v, lson);
 79             update(mid + 
1, R, v, rson);
 80         }
 81         Up(seg[rt], seg[rt << 
1], seg[rt << 
1 | 
1]);
 82         
//
 83 
    } 
else {
 84         Down(seg[rt], seg[rt << 
1], seg[rt << 
1 | 
1], r - l + 
1);
 85         
if (R <= mid) update(L, R, v, lson);
 86         
else 
if (L > mid) update(L, R, v, rson);
 87         
else {
 88             update(L, mid, v, lson);
 89             update(mid + 
1, R, v, rson);
 90         }
 91         Up(seg[rt], seg[rt << 
1], seg[rt << 
1 | 
1]);
 92     }
 93 }
 94 
int n;
 95 
 96 
int nex[N], hap[N];
 97 
 98 
void work() {
 99     
for (
int i = 
1; i <= n; ++i) {
100         scanf(
"
%d
", &ar[i]);
101         
if (ar[i] > n)
102             ar[i] = n + 
1;
103     }
104     memset(vis, 
0
sizeof(vis));
105     idx = 
0;
106     build(
1, n, 
1);
107     ll ans = query(
1, n, 
1, n, 
1);
108 
109     memset(hap, -
1
sizeof(hap));
110     memset(nex, -
1
sizeof(nex));
111 
112     
for (
int i = 
1; i <= n; ++i) {
113         
if (hap[ar[i]] == -
1)
114             hap[ar[i]] = i;
115         
else {
116             nex[hap[ar[i]]] = i;
117             hap[ar[i]] = i;
118         }
119     }
120 
121     
int to;
122     
for (
int i = 
1; i <= n - 
1; ++i) {
123         
if (nex[i] == -
1)
124             to = n;
125         
else
126             to = nex[i] - 
1;
127         update(i, to, ar[i], 
1, n, 
1);
128         ans = ans + query(i, n, 
1, n, 
1);
129     }
130     printf(
"
%I64d\n
", ans);
131 }
132 
int main() {
133     
while (
1 == scanf(
"
%d
", &n)) {
134         
if (
0 == n) 
break;
135         work();
136     }
137     
return 
0;
138 }
View Code 

CLJ有一个很诡异的map解法

ExpandedBlockStart.gif
 1 #include <vector>
 2 #include <
string>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <
set>
 7 #include <map>
 8 #include <sstream>
 9 #include <iomanip>
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cstring>
13 #include <cmath>
14 
using 
namespace std;
15 typedef 
long 
long ll;
16 typedef 
double du;
17 
#define pb push_back
18 
#define mp make_pair
19 
#define fi first
20 
#define se second
21 
#define FOR(i, s, t) for(i = (s); i < (t); i++)
22 
#define RFOR(i, s, t) for(i = (s)-1; i >= (t); i--)
23 
const 
int MAXN = 
200004;
24 
25 
int a[MAXN];
26 
int nextSame[MAXN], next[MAXN];
27 
bool vis[MAXN];
28 map<
int
int> s;
29 
30 
int main()
31 {
32     #ifdef __FIO
33     freopen(
"
in.txt
"
"
r
", stdin);
34     
//
freopen("out.txt", "w", stdout);
35 
    
#endif
36     
int T;
37     
//
scanf("%d", &T);
38 
    
while(
1){
39         
int n;
40         
int i, j, k;
41         
int si;
42         ll sum, tsum;
43         sum = tsum = 
0;
44         scanf(
"
%d
", &n);
45         
if(n == 
0)
46             
break;
47         
for(i = 
0; i < n; i++){
48             scanf(
"
%d
", &a[i]);
49             
if(a[i] > n)
50                 a[i] = n+
1;
51         }
52         
for(i = 
0; i <= n+
1; i++)
53             next[i] = n;
54         
for(i = n-
1; i >= 
0; i--){
55             nextSame[i] = next[a[i]];
56             next[a[i]] = i;
57         }
58         memset(vis, 
0
sizeof vis);
59         j = 
0;
60         s.clear();
61         
for(i = 
0; i < n; i++){
62             vis[a[i]] = 
true;
63             
while(vis[j])
64                 j++;
65             tsum += j;
66             s[i] = j;
67         }
68         s[n] = n;
69         sum += tsum;
70         
for(i = 
0; i < n-
1; i++){
71             tsum -= s.begin()->se;
72             s[i] = -
1;
73             map<
int
int>::iterator it = s.lower_bound(nextSame[i]-
1);
74             
if(it->se > a[i]){
75                 
if(it->fi >= nextSame[i]){
76                     
int temp = it->se-a[i];
77                     tsum -= (ll)temp*(nextSame[i]-
1);
78                     it--;
79                     tsum += (ll)temp*it->fi;
80                 }
81                 
while(it->se >= a[i]){
82                     
int temp = it->se-a[i];
83                     tsum -= (ll)temp*it->fi;
84                     s.erase(it--);
85                     tsum += (ll)temp*it->fi;
86                 }
87                 s[nextSame[i]-
1] = a[i];
88             }
89             s.erase(i);
90             sum += tsum;
91         }
92         printf(
"
%I64d\n
", sum);
93     }
94     
return 
0;
95 }
View Code 

 

转载于:https://www.cnblogs.com/hewifi/p/3329168.html

你可能感兴趣的文章
[洛谷1485] 火枪打怪
查看>>
PAT B1018.锤子剪刀布(20)
查看>>
Extjs控件之 grid打印功能
查看>>
枚举类型(不常用)递归
查看>>
ETL
查看>>
Tomcat源码分析(六)--日志记录器和国际化
查看>>
minggw 安装
查看>>
Jquery操作cookie,实现简单的记住用户名的操作
查看>>
[BZOJ1196][HNOI2006]公路修建问题 二分答案+最小生成树
查看>>
PHP基础入门(二)
查看>>
[Luogu P3119] [USACO15JAN]草鉴定Grass Cownoisseur (缩点+图上DP)
查看>>
【原创】大数据基础之Zookeeper(4)应用场景
查看>>
18款在线代码片段测试工具
查看>>
20.C++- &&,||逻辑重载操作符的缺陷、,逗号重载操作符的分析
查看>>
静态变量数组实现LRU算法
查看>>
在SQL中怎么把一列字符串拆分为多列
查看>>
中文系统 上传file的input显示英文
查看>>
css样式写一个三角形
查看>>
比callback更简洁的链式执行promise
查看>>
android permission
查看>>