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 }
View Code

 

——written by Lyon

转载于:https://www.cnblogs.com/LyonLys/p/uva_12003_Lyon.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值