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 }  

时间: 2024-08-01 13:33:23

hdu 4417 Super Mario/树套树的相关文章

HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5101    Accepted Submission(s): 2339 Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping abilit

HDU 4417 Super Mario (划分树)(二分)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6077    Accepted Submission(s): 2645 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping ab

hdu 4417 Super Mario (线段树+动态数组)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2685    Accepted Submission(s): 1306 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping a

hdu 4417 Super Mario (主席树)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意: 给你段长为n的序列,有q个询问,每次询问区间[l.r]内有多少个数小于等于k 思路: 之前用分块写过类似的,不过为了练习下主席树,这里用主席树写了下.思路很简单 离线离散化处理下,每次插入一个数num时,在主席树上下标num+1,这样每次询问[l,r]中有多少个小于k的数的时候,我们只要找下标[1,k]的区间第R次修改后的总和减去第L-1次修改后的总值就可以得到了 实现代码: #inclu

HDU 4417 Super Mario(离线线段树or树状数组)

Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover. We regard the road to the boss's castle as a l

hdu 4417 Super Mario(主席树)

题意:给你一些数,有多次询问,问你在l,r区间内小于k的数有多少个 思路:主席树大发好,虽然树状数组和线段树离线也可以做 代码: #include <set> #include <map> #include <queue> #include <stack> #include <math.h> #include <vector> #include <string> #include <stdio.h> #incl

HDU 4417 Super Mario ( 超级马里奥 + 主席树 + 线段树/树状数组离线处理 + 划分树 )

HDU 4417 - Super Mario ( 主席树 + 线段树/树状数组离线处理 + 划分树 ) 这道题有很多种做法,我先学习的是主席树.后面陆续补上线段树离线和划分树 题目大意就是给定一个区间给定一个数列,每次要求你查询区间[L,R]内不超过K的数的数量 主席树做法: 最基本的是静态第k大,这里是求静态的 <= K,差不多,在Query操作里面需要修改修改 先建立size棵主席树,然后询问的时候统计的是 第R棵主席树中[1,K]的数量 - 第L-1棵主席树中[1,K]的数量 注意这里下标

HDU 4417 Super Mario (树状数组/线段树)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble agai

hdu 4417 Super Mario(离线树状数组|划分树)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2584    Accepted Submission(s): 1252 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping a