zoukankan      html  css  js  c++  java
  • [HDOJ4417]Super Mario(归并树)

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

    题意:给定n个数和q次询问,每次询问[l,r]区间内不比k大的数字的个数。

    直接上归并树,每次查询直接查区间内小于等于k的数的个数,二分即可。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define lrt rt << 1
     5 #define rrt rt << 1 | 1
     6 const int maxn = 100100;
     7 int n, q, a[maxn];
     8 vector<int> seg[maxn<<2];
     9 
    10 void build(int l, int r, int rt) {
    11     if(l == r) {
    12         seg[rt].clear();
    13         seg[rt].push_back(a[l]);
    14         return;
    15     }
    16     int mid = (l + r) >> 1;
    17     build(l, mid, lrt);
    18     build(mid+1, r, rrt);
    19     seg[rt].resize(r-l+1);
    20     merge(seg[lrt].begin(), seg[lrt].end(), seg[rrt].begin(), seg[rrt].end(), seg[rt].begin());
    21 }
    22 
    23 int query(int L, int R, int v, int l, int r, int rt) {
    24     if(R < l || r < L) return 0;
    25     if(L <= l && r <= R) return upper_bound(seg[rt].begin(), seg[rt].end(), v) - seg[rt].begin();
    26     int mid = (l + r) >> 1;
    27     return query(L, R, v, l, mid, lrt) + query(L, R, v, mid+1, r, rrt);
    28 }
    29 
    30 inline bool scan_d(int &num) {
    31     char in;bool IsN=false;
    32     in=getchar();
    33     if(in==EOF) return false;
    34     while(in!='-'&&(in<'0'||in>'9')) in=getchar();
    35     if(in=='-'){ IsN=true;num=0;}
    36     else num=in-'0';
    37     while(in=getchar(),in>='0'&&in<='9'){
    38         num*=10,num+=in-'0';
    39     }
    40     if(IsN) num=-num;
    41     return true;
    42 }
    43 
    44 inline void out(int x) { 
    45     if (x > 9) out(x / 10); 
    46     putchar(x % 10 + '0');
    47 }
    48 
    49 int main() {
    50     // freopen("in", "r", stdin);
    51     // freopen("out", "w", stdout);
    52     int T, l, r, k, _ = 1;
    53     scan_d(T);
    54     while(T--) {
    55         scan_d(n); scan_d(q);
    56         for(int i = 1; i <= n; i++) scan_d(a[i]);
    57         build(1, n, 1);
    58         sort(a+1, a+n+1);
    59         printf("Case %d:
    ", _++);
    60         while(q--) {
    61             scan_d(l); scan_d(r); scan_d(k);
    62             l++; r++;
    63             int lo = 1, hi = n;
    64             int ret = query(l, r, k, 1, n, 1);
    65             printf("%d
    ", ret);
    66         }
    67     }
    68     return 0;
    69 }

    用数组写了个,快了不少。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define lrt rt << 1
     5 #define rrt rt << 1 | 1
     6 const int maxn = 100100;
     7 int n, q, a[maxn];
     8 int ll[maxn], rr[maxn];
     9 int seg[20][maxn];
    10 
    11 void build(int l, int r, int rt) {
    12     if(l == r) {
    13         seg[rt][l] = a[l];
    14         return;
    15     }
    16     int mid = (l + r) >> 1;
    17     build(l, mid, rt+1);
    18     build(mid+1, r, rt+1);
    19     // merge(seg[rt+1]+l, seg[rt+1]+mid+1, seg[rt+1]+mid+1, seg[rt+1]+r+1, seg[rt]+l);
    20     int n1 = mid - l + 1, n2 = r - (mid + 1) + 1;
    21     int i = 0, j = 0;
    22     for(int ii = 0; ii < n1; ii++) ll[ii] = seg[rt+1][l+ii];
    23     for(int ii = 0; ii < n2; ii++) rr[ii] = seg[rt+1][(mid+1)+ii];
    24     while(i < n1 && j < n2) {
    25         if(ll[i] <= rr[j]) seg[rt][l++] = ll[i++];
    26         else seg[rt][l++] = rr[j++];
    27     }
    28     while(i < n1) seg[rt][l++] = ll[i++];
    29     while(j < n2) seg[rt][l++] = rr[j++];
    30 }
    31 
    32 int query(int L, int R, int v, int l, int r, int rt) {
    33     if(r < L || R < l) return 0;
    34     if(L <= l && r <= R) return upper_bound(seg[rt]+l, seg[rt]+r+1, v) - (seg[rt]+l);
    35     int mid = (l + r) >> 1;
    36     return query(L, R, v, l, mid, rt+1) + query(L, R, v, mid+1, r, rt+1);
    37 }
    38 
    39 int main() {
    40     // freopen("in", "r", stdin);
    41     // freopen("out", "w", stdout);
    42     int T, l, r, k, _ = 1;
    43     scanf("%d", &T);
    44     while(T--) {
    45         scanf("%d%d",&n,&q);
    46         for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    47         build(1, n, 1);
    48         printf("Case %d:
    ", _++);
    49         while(q--) {
    50             scanf("%d%d%d",&l,&r,&k);
    51             l++; r++;
    52             int lo = 1, hi = n;
    53             int ret = query(l, r, k, 1, n, 1);
    54             printf("%d
    ", ret);
    55         }
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    Redis学习笔记-安装篇(Centos7)
    图片上传预览方式,了解下?
    Angular中依赖注入方式的几种写法
    Javascript实现打开或退出浏览器全屏
    从头开始学Web开发—CSS_01
    JavaScript DOM知识 (一)
    javascript中的scroll事件
    javascript中继承的实现
    认识Javascript中的作用域和作用域链
    javascript中的闭包
  • 原文地址:https://www.cnblogs.com/kirai/p/6927649.html
Copyright © 2011-2022 走看看