Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem E (Codeforces 831E) - 线段树 - 树状数组
Vasily has a deck of cards consisting of n cards. There is an integer on each of the cards, this integer is between 1 and 100 000, inclusive. It is possible that some cards have the same integers on them.
Vasily decided to sort the cards. To do this, he repeatedly takes the top card from the deck, and if the number on it equals the minimum number written on the cards in the deck, then he places the card away. Otherwise, he puts it under the deck and takes the next card from the top, and so on. The process ends as soon as there are no cards in the deck. You can assume that Vasily always knows the minimum number written on some card in the remaining deck, but doesn't know where this card (or these cards) is.
You are to determine the total number of times Vasily takes the top card from the deck.
The first line contains single integer n (1 ≤ n ≤ 100 000) — the number of cards in the deck.
The second line contains a sequence of n integers a1, a2, ..., an (1 ≤ ai ≤ 100 000), where ai is the number written on the i-th from top card in the deck.
Print the total number of times Vasily takes the top card from the deck.
4
6 3 1 2
7
1
1000
1
7
3 3 3 3 3 3 3
7
In the first example Vasily at first looks at the card with number 6 on it, puts it under the deck, then on the card with number 3, puts it under the deck, and then on the card with number 1. He places away the card with 1, because the number written on it is the minimum among the remaining cards. After that the cards from top to bottom are [2, 6, 3]. Then Vasily looks at the top card with number 2 and puts it away. After that the cards from top to bottom are [6, 3]. Then Vasily looks at card 6, puts it under the deck, then at card 3 and puts it away. Then there is only one card with number 6 on it, and Vasily looks at it and puts it away. Thus, in total Vasily looks at 7 cards.
题目大意 桌面上有一叠卡牌,每张卡牌上有些数。当拿起一张卡牌时,如果它上面的数是当前剩下的牌中的数(包括拿起的这一张)的最小值(假定这个人知道),就把它"扔掉",否则把它塞进这叠卡牌的最下面。问把所有卡牌都拿走花了多少次。
然后不说多的废话了。树状数组维护卡牌是否被拿走(拿走为0,未拿走为1),线段树维护区间最小值。
因为移动的话很麻烦,但是一轮后顺序又正常了,所以可以一轮一轮地计算。记录fin(已经拿走的牌的数量)和last(上个拿走的卡牌的下标)。
->当fin等于n时停止
->将last设为1
->找到last右侧的最小值和整叠卡牌的最小值,判断他们是否相等。
*如果相等
->返回最小的最小值下标pos,然后树状数组统计last + 1到pos的和(这中间还有多少没拿走),更新答案。
->将树状数组这一位置为0,线段树中这一位改为inf(不方便delete,就这么干),fin 加 1,将last设为pos。
*如果不相等
->统计last + 1到n的和(把这一轮中剩下的牌都拿完)
->break
Code
1 /** 2 * Codeforces 3 * Problem#831E 4 * Accepted 5 * Time:109ms 6 * Memory:7584k 7 */ 8 #include <iostream> 9 #include <cstdio> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #include <cstring> 14 #include <cstdlib> 15 #include <fstream> 16 #include <sstream> 17 #include <algorithm> 18 #include <map> 19 #include <set> 20 #include <stack> 21 #include <queue> 22 #include <vector> 23 #include <stack> 24 #include <cassert> 25 #ifndef WIN32 26 #define Auto "%lld" 27 #else 28 #define Auto "%I64d" 29 #endif 30 using namespace std; 31 typedef bool boolean; 32 const signed int inf = (signed)((1u << 31) - 1); 33 const signed long long llf = (signed long long)((1ull << 61) - 1); 34 const double eps = 1e-6; 35 const int binary_limit = 128; 36 #define smin(a, b) a = min(a, b) 37 #define smax(a, b) a = max(a, b) 38 #define max3(a, b, c) max(a, max(b, c)) 39 #define min3(a, b, c) min(a, min(b, c)) 40 template<typename T> 41 inline boolean readInteger(T& u){ 42 char x; 43 int aFlag = 1; 44 while(!isdigit((x = getchar())) && x != '-' && x != -1); 45 if(x == -1) { 46 ungetc(x, stdin); 47 return false; 48 } 49 if(x == '-'){ 50 x = getchar(); 51 aFlag = -1; 52 } 53 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 54 ungetc(x, stdin); 55 u *= aFlag; 56 return true; 57 } 58 59 #define lowbit(x) (x & (-x)) 60 61 typedef class IndexedTree { 62 public: 63 int *l; 64 int size; 65 66 IndexedTree() { } 67 IndexedTree(int size):size(size) { 68 l = new int[(size + 1)]; 69 memset(l, 0, sizeof(int) * (size + 1)); 70 } 71 72 inline void add(int idx, int val) { 73 for(; idx <= size; idx += lowbit(idx)) { 74 l[idx] += val; 75 } 76 } 77 78 inline int getSum(int idx) { 79 int ret = 0; 80 for(; idx; idx -= lowbit(idx)) 81 ret += l[idx]; 82 return ret; 83 } 84 }IndexedTree; 85 86 typedef class SegTreeNode { 87 public: 88 int minid; 89 int val; 90 SegTreeNode *l, *r; 91 92 SegTreeNode() { } 93 94 inline void pushUp() { 95 if(l->val <= r->val) 96 minid = l->minid, val = l->val; 97 else 98 minid = r->minid, val = r->val; 99 } 100 }SegTreeNode; 101 102 typedef class SegTree { 103 public: 104 SegTreeNode* root; 105 106 SegTree() { } 107 SegTree(int n, int* lis) { 108 build(root, 1, n, lis); 109 } 110 111 void build(SegTreeNode* &node, int l, int r, int *lis) { 112 node = new SegTreeNode(); 113 if(l == r) { 114 node->minid = l, node->val = lis[l]; 115 return; 116 } 117 int mid = (l + r) >> 1; 118 build(node->l, l, mid, lis); 119 build(node->r, mid + 1, r, lis); 120 node->pushUp(); 121 } 122 123 void update(SegTreeNode* &node, int l, int r, int idx, int val) { 124 if(l == idx && r == idx) { 125 node->val = val; 126 return; 127 } 128 int mid = (l + r) >> 1; 129 if(idx <= mid) update(node->l, l, mid, idx, val); 130 else update(node->r, mid + 1, r, idx, val); 131 node->pushUp(); 132 } 133 134 void query(SegTreeNode*& node, int l, int r, int ql, int qr, int& idx, int& minv) { 135 if(l == ql && r == qr) { 136 if(node->val < minv) 137 idx = node->minid, minv = node->val; 138 return; 139 } 140 int mid = (l + r) >> 1; 141 if(qr <= mid) query(node->l, l, mid, ql, qr, idx, minv); 142 else if(ql > mid) query(node->r, mid + 1, r, ql, qr, idx, minv); 143 else { 144 int a = -1, b = inf; 145 query(node->l, l, mid, ql, mid, a, b); 146 query(node->r, mid + 1, r, mid + 1, qr, idx, minv); 147 if(b <= minv) { 148 minv = b, idx = a; 149 } 150 } 151 } 152 }SegTree; 153 154 int n; 155 int *a; 156 IndexedTree st; 157 SegTree st1; 158 159 inline void init() { 160 readInteger(n); 161 a = new int[n + 1]; 162 for(int i = 1; i <= n; i++) { 163 readInteger(a[i]); 164 } 165 } 166 167 long long res = 0; 168 inline void solve() { 169 st = IndexedTree(n); 170 st1 = SegTree(n, a); 171 for(int i = 1; i <= n; i++) st.add(i, 1); 172 173 for(int fin = 0; fin < n; ) { 174 for(int last = 0; fin < n && last < n; ) { 175 int stand, idx, minv1 = inf, minv2 = inf; 176 st1.query(st1.root, 1, n, 1, n, stand, minv1); 177 st1.query(st1.root, 1, n, last + 1, n, idx, minv2); 178 if(minv1 != minv2) { 179 res += st.getSum(n) - st.getSum(last); 180 break; 181 } 182 res += st.getSum(idx) - st.getSum(last); 183 st.add(idx, -1); 184 st1.update(st1.root, 1, n, idx, inf); 185 fin++; 186 last = idx; 187 } 188 } 189 printf(Auto, res); 190 } 191 192 int main() { 193 init(); 194 solve(); 195 return 0; 196 }