hdu 4417 Super Mario/树套树

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417

题意很简单,给定一个序列求一个区间 [L, R,]中小于等于H的元素的个数。

好像函数式线段树可解吧,可弱弱的沙茶一直没弄懂其精髓,只好用树套树暴力碾压了敲打

额树套树,线段树的每一个节点套一个sb树。

当查询[l,r]区间中的值小于等于H的个数,先用线段树找到相应的区间,

然后再查询该区间下对应的平衡树中小于等于H的个数,累加即可。

一直以为会超时,结果400+ms就过了,数据应该很弱吧(自己对拍了一组(N,M)10w规模的跑了2s多o(╯□╰)o)。

  1 #include<cstdio>    

  2 #include<cstdlib>    

  3 #include<cstring>    

  4 #include<algorithm>    

  5 #define lc root<<1    

  6 #define rc root<<1|1    

  7 const int Max_N = 100100;  

  8 struct SBT{  

  9     int v, s, c;  

 10     SBT *ch[2];  

 11     inline void set(int _v = 0){  

 12         v = _v, c = s = 1;  

 13         ch[0] = ch[1] = null;  

 14     }  

 15     inline void push_up(){  

 16         s = ch[0]->s + ch[1]->s + c;  

 17     }  

 18     inline int cmp(int x) const{  

 19         return v == x ? -1 : x > v;  

 20     }  

 21 }*null, stack[Max_N << 3], *ptr[Max_N << 2];  

 22 int sz = 0, sum = 0, arr[Max_N];  

 23 void init(){  

 24     null = &stack[sz++];  

 25     null->v = null->s = null->c = 0;  

 26 }  

 27 inline void rotate(SBT* &x, int d){  

 28     SBT *k = x->ch[!d];  

 29     x->ch[!d] = k->ch[d];  

 30     k->ch[d] = x;  

 31     k->s = x->s;;  

 32     x->push_up();  

 33     x = k;  

 34 }  

 35 void Maintain(SBT* &x, int d){  

 36     if (x->ch[d] == null) return;  

 37     if (x->ch[d]->ch[d]->s > x->ch[!d]->s){  

 38         rotate(x, !d);  

 39     } else if (x->ch[d]->ch[!d]->s > x->ch[d]->s){  

 40         rotate(x->ch[d], d), rotate(x, !d);  

 41     } else {  

 42         return;  

 43     }  

 44     Maintain(x, 0), Maintain(x, 1);  

 45 }  

 46 void insert(SBT* &x, int v){  

 47     if (x == null){  

 48         x = &stack[sz++];  

 49         x->set(v);  

 50     } else {  

 51         x->s++;  

 52         int d = x->cmp(v);  

 53         if (-1 == d){  

 54             x->c++;  

 55             return;  

 56         }  

 57         insert(x->ch[d], v);  

 58         x->push_up();  

 59         Maintain(x, d);  

 60     }  

 61 }  

 62 int sbt_rank(SBT *x, int key){  

 63     int t, cur;  

 64     for (t = cur = 0; x != null;){  

 65         t = x->ch[0]->s;  

 66         if (key < x->v) x = x->ch[0];  

 67         else if (key >= x->v) cur += x->c + t, x = x->ch[1];  

 68     }  

 69     return cur;  

 70 }  

 71 void seg_built(int root, int l, int r){  

 72     ptr[root] = null;  

 73     for (int i = l; i <= r; i++) insert(ptr[root], arr[i]);  

 74     if (l == r) return;  

 75     int mid = (l + r) >> 1;  

 76     seg_built(lc, l, mid);  

 77     seg_built(rc, mid + 1, r);  

 78 }  

 79 void seg_rank(int root, int l, int r, int x, int y, int v){  

 80     if (x > r || y < l) return;  

 81     if (x <= l && y >= r){  

 82         sum += sbt_rank(ptr[root], v);  

 83         return;  

 84     }  

 85     int mid = (l + r) >> 1;  

 86     seg_rank(lc, l, mid, x, y, v);  

 87     seg_rank(rc, mid + 1, r, x, y, v);  

 88 }  

 89 int main(){  

 90 #ifdef LOCAL  

 91     freopen("in.txt", "r", stdin);  

 92     freopen("out.txt", "w+", stdout);  

 93 #endif  

 94     int i, t, n, m, a, b, c, k = 1;  

 95     scanf("%d", &t);  

 96     while (t--){  

 97         sz = 0, init();  

 98         scanf("%d %d", &n, &m);  

 99         printf("Case %d:\n", k++);  

100         for (i = 1; i <= n; i++) scanf("%d", &arr[i]);  

101         seg_built(1, 1, n);  

102         while (m--){  

103             scanf("%d %d %d", &a, &b, &c);  

104             sum = 0;  

105             seg_rank(1, 1, n, a + 1, b + 1, c);  

106             printf("%d\n", sum);  

107         }  

108     }  

109     return 0;  

110 }  
View Code

 

你可能感兴趣的:(super)