uva 12003 Array Transformer (线段树套平衡树)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3154
题意是,要求求出区间中小于某个值的数有多少个,然后利用这个个数来更新某个点的值。
直接树套树解决问题,不过这题时间卡的比较紧。留心观察可以发现,询问的数目其实是比较小的,可是总的个数多大30W。如果是O(n*logn*logn)的复杂度建树就会超时,估计这里就是卡这一个了。其余的都不难,不过就是开始的时候没有看出可以卡时间卡这么紧,没有建树的经验,所以直接暴力插点,一直TLE。中间的时候sbt又写错了,为了debug个RE又搞了半天。
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <ctime> 6 #include <set> 7 #include <cctype> 8 #include <cmath> 9 10 using namespace std; 11 12 #define lson l, m, rt << 1 13 #define rson m + 1, r, rt << 1 | 1 14 #define root 1, n, 1 15 16 const int N = 333333; 17 typedef long long LL; 18 19 struct Node { 20 Node *c[2]; 21 int ky, sz; 22 void init(int k = 0) { 23 ky = k; 24 sz = 1; 25 c[0] = c[1] = NULL; 26 } 27 } node[N * 25]; 28 int ttnd; 29 30 void init() { ttnd = 0;} 31 32 struct Treap { 33 Node *RT; 34 void init() { RT = NULL;} 35 int size() { return RT->sz;} 36 void make(int *arr, int l, int r, Node *&rt) { 37 if (l > r) return ; 38 if (l == r) { 39 rt = node + ttnd++; 40 rt->init(arr[l]); 41 return ; 42 } 43 int m = l + r >> 1; 44 rt = node + ttnd++; 45 rt->init(arr[m]); 46 make(arr, l, m - 1, rt->c[0]); 47 make(arr, m + 1, r, rt->c[1]); 48 rt->sz = (rt->c[0] ? rt->c[0]->sz : 0) + (rt->c[1] ? rt->c[1]->sz : 0) + 1; 49 } 50 void make(int *arr, int l, int r) { 51 init(); 52 make(arr, l, r, RT); 53 } 54 void rotate(Node *&rt, bool l) { 55 bool r = !l; 56 Node *p = rt->c[l]; 57 rt->c[l] = p->c[r]; 58 p->c[r] = rt; 59 p->sz = rt->sz; 60 rt->sz = (rt->c[0] ? rt->c[0]->sz : 0) + (rt->c[1] ? rt->c[1]->sz : 0) + 1; 61 rt = p; 62 } 63 void maintain(Node *&rt, bool r) { 64 if (!rt || !rt->c[r]) return ; 65 bool l = !r; 66 int ls = rt->c[l] ? rt->c[l]->sz : 0; 67 if (rt->c[r]->c[r] && rt->c[r]->c[r]->sz > ls) { 68 rotate(rt, r); 69 } else if (rt->c[r]->c[l] && rt->c[r]->c[l]->sz > ls) { 70 rotate(rt->c[r], l), rotate(rt, r); 71 } else return ; 72 maintain(rt->c[0], false); 73 maintain(rt->c[1], true); 74 maintain(rt, false); 75 maintain(rt, true); 76 } 77 void insert(Node *&rt, Node *x) { 78 if (!rt) { 79 rt = x; 80 return ; 81 } 82 rt->sz++; 83 if (x->ky < rt->ky) insert(rt->c[0], x); 84 else insert(rt->c[1], x); 85 maintain(rt, x->ky >= rt->ky); 86 } 87 void insert(int k) { 88 Node *tmp = node + ttnd++; 89 tmp->init(k); 90 insert(RT, tmp); 91 } 92 void erase(Node *&rt, int k) { 93 if (!rt) return ; 94 rt->sz--; 95 if (k < rt->ky) erase(rt->c[0], k); 96 else if (k > rt->ky) erase(rt->c[1], k); 97 else { 98 if (!rt->c[0] && !rt->c[1]) rt = NULL; 99 else if (!rt->c[0]) rt = rt->c[1]; 100 else if (!rt->c[1]) rt = rt->c[0]; 101 else { 102 Node *t = rt->c[1]; 103 while (t->c[0]) t = t->c[0]; 104 rt->ky = t->ky; 105 erase(rt->c[1], t->ky); 106 } 107 } 108 if (rt) rt->sz = (rt->c[0] ? rt->c[0]->sz : 0) + (rt->c[1] ? rt->c[1]->sz : 0) + 1; 109 } 110 void pre(Node *x) { 111 if (!x) return ; 112 cout << x << ' ' << x->c[0] << ' ' << x->c[1] << ' ' << x->ky << ' ' << x->sz << endl; 113 pre(x->c[0]); 114 pre(x->c[1]); 115 } 116 void erase(int k) { erase(RT, k);} 117 int find(Node *rt, int k) { 118 if (!rt) return 0; 119 int ret = 0; 120 if (k > rt->ky) ret = (rt->c[0] ? rt->c[0]->sz : 0) + find(rt->c[1], k) + 1; 121 else ret = find(rt->c[0], k); 122 return ret; 123 } 124 int lower_bound(int k) { return find(RT, k);} 125 } trp[N << 2]; 126 127 int pos[N], rec[N], ori[N]; 128 void build(int l, int r, int rt) { 129 if (l == r) { 130 trp[rt].make(rec, l, r); 131 pos[l] = rt; 132 return ; 133 } 134 int m = l + r >> 1; 135 build(lson); 136 build(rson); 137 sort(rec + l, rec + r + 1); 138 trp[rt].make(rec, l, r); 139 } 140 141 void insert(int p, int x, int d) { 142 if (p <= 0) return ; 143 trp[p].erase(d); 144 trp[p].insert(x); 145 insert(p >> 1, x, d); 146 } 147 148 int query(int L, int R, int x, int l, int r, int rt) { 149 if (L <= l && r <= R) return trp[rt].lower_bound(x); 150 int m = l + r >> 1, ret = 0; 151 if (L <= m) ret += query(L, R, x, lson); 152 if (m < R) ret += query(L, R, x, rson); 153 return ret; 154 } 155 156 void scan(int &x) { 157 char ch; 158 while (!isdigit(ch = getchar())) ; 159 x = ch - '0'; 160 while (isdigit(ch = getchar())) x = x * 10 + ch - '0'; 161 } 162 163 int main() { 164 //freopen("in", "r", stdin); 165 int n, m, u; 166 while (~scanf("%d%d%d", &n, &m, &u)) { 167 init(); 168 for (int i = 1; i <= n; i++) { 169 scan(rec[i]); 170 ori[i] = rec[i]; 171 } 172 build(root); 173 int L, R, v, p; 174 while (m--) { 175 scan(L), scan(R), scan(v), scan(p); 176 int k = query(L, R, v, root); 177 k = (LL) u * k / (R - L + 1); 178 insert(pos[p], k, ori[p]); 179 ori[p] = k; 180 } 181 for (int i = 1; i <= n; i++) printf("%d\n", ori[i]); 182 } 183 return 0; 184 }
——written by Lyon