zoukankan      html  css  js  c++  java
  • HDU3473--Minimum Sum(静态区间第k大)

    Minimum Sum

    Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 3047    Accepted Submission(s): 701


    Problem Description
    You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you some intervals [l, r]. For each interval, you need to find a number x to make as small as possible!
     


    Input
    The first line is an integer T (T <= 10), indicating the number of test cases. For each test case, an integer N (1 <= N <= 100,000) comes first. Then comes N positive integers x (1 <= x <= 1,000, 000,000) in the next line. Finally, comes an integer Q (1 <= Q <= 100,000), indicting there are Q queries. Each query consists of two integers l, r (0 <= l <= r < N), meaning the interval you should deal with.

     


    Output
    For the k-th test case, first output “Case #k:” in a separate line. Then output Q lines, each line is the minimum value of  . Output a blank line after every test case.
     


    Sample Input
    2
    5
    3 6 2 2 4
    2
    1 4
    0 2
    2
    7 7
    2
    0 1
    1 1
     


    Sample Output
    Case #1:
    6
    4
     
     
    Case #2:
    0
    0
     

    区间第k大的题目一般两种做法,,划分树 主席树,不过貌似划分树只支持静态区间第k大。


    这道题由于内存限制 只能用划分树。。具体就是 先找出区间[l,r]内的中位数,(为什么是中位数,大白书貌似有介绍),然后直接求和。

    MLE到死啊,,注释memset部分之后就过了,不知道为什么
    划分树代码:

      1 #include <set>
      2 #include <map>
      3 #include <cmath>
      4 #include <ctime>
      5 #include <queue>
      6 #include <stack>
      7 #include <cstdio>
      8 #include <string>
      9 #include <vector>
     10 #include <cstdlib>
     11 #include <cstring>
     12 #include <iostream>
     13 #include <algorithm>
     14 using namespace std;
     15 typedef unsigned long long ull;
     16 typedef long long ll;
     17 const int inf = 0x3f3f3f3f;
     18 const double eps = 1e-8;
     19 const int maxn = 100010;
     20 int sorted[maxn],tree[20][maxn],toleft[20][maxn];   //toleft[dep][i]表示第dep层1-i中进入左子树元素的个数
     21 ll leftsum[20][maxn], sum[maxn];              //leftsum[dep][i]表示第dep层1-i中进入左子树元素的和
     22 
     23 void build (int l,int r,int dep)
     24 {
     25     if (l == r)
     26         return;
     27     int mid = (l + r) >> 1;
     28     int same = mid - l + 1;
     29     for (int i = l; i <= r; i++)
     30         if (tree[dep][i] < sorted[mid])
     31             same--;
     32     int lpos = l,rpos = mid + 1;
     33     for (int i = l; i <= r; i++)
     34     {
     35         if (tree[dep][i] < sorted[mid])
     36         {
     37             tree[dep+1][lpos++] = tree[dep][i];
     38             leftsum[dep][i] = leftsum[dep][i-1] + tree[dep][i];
     39         }
     40         else if (tree[dep][i] == sorted[mid] && same > 0)
     41         {
     42             tree[dep+1][lpos++] = tree[dep][i];
     43             leftsum[dep][i] = leftsum[dep][i-1] + tree[dep][i];
     44             same--;
     45         }
     46         else
     47         {
     48             tree[dep+1][rpos++] = tree[dep][i];
     49             leftsum[dep][i] = leftsum[dep][i-1];
     50         }
     51         toleft[dep][i] = toleft[dep][l-1] + lpos - l;
     52     }
     53     build (l,mid,dep+1);
     54     build (mid+1,r,dep+1);
     55 }
     56 int lnum,rnum;
     57 ll lsum,rsum;
     58 int query(int l,int r,int dep,int ua,int ub,int k)
     59 {
     60     if (ua == ub)
     61         return tree[dep][ua];
     62     int mid = (l + r) >> 1;
     63     int cnt = toleft[dep][ub] - toleft[dep][ua-1];
     64     if (cnt >= k)
     65     {
     66         int newl = l + toleft[dep][ua-1] - toleft[dep][l-1];
     67         int newr = newl + cnt - 1;
     68         return query(l,mid,dep+1,newl,newr,k);
     69     }
     70     else
     71     {
     72         int newr = ub + toleft[dep][r] - toleft[dep][ub];
     73         int newl = newr - (ub - ua - cnt);
     74         lnum += cnt;
     75         lsum += leftsum[dep][ub] - leftsum[dep][ua-1];
     76         return query(mid+1,r,dep+1,newl,newr,k-cnt);
     77     }
     78 }
     79 
     80 int main(void)
     81 {
     82     #ifndef ONLINE_JUDGE
     83         freopen("in.txt","r",stdin);
     84     #endif
     85     int T, cas = 1;
     86     scanf ("%d",&T);
     87     while (T--)
     88     {
     89         int n,m;
     90         scanf ("%d",&n);
     91         sum[0] = 0;
     92         for (int i = 1; i <= n; i++)
     93         {
     94             scanf ("%d",&tree[0][i]);
     95             sum[i] = sum[i-1] + tree[0][i];
     96             sorted[i] = tree[0][i];
     97         }
     98         sort(sorted+1,sorted+n+1);
     99         build (1,n,0);
    100         scanf ("%d",&m);
    101         printf ("Case #%d:
    ",cas++);
    102         while (m--)
    103         {
    104             int u, v;
    105             scanf ("%d%d",&u,&v);
    106             u++,v++;
    107             lnum = 0;
    108             lsum = 0;
    109             int mid_num = query(1,n,0,u,v,(v-u)/2+1);             //中位数
    110             rnum = (v - u + 1 - lnum);                            // u~v 区间内大于mid_num的个数
    111             rsum = (sum[v] - sum[u-1] - lsum);                    //u~v    区间内大于mid_num的数的和
    112             ll ans = rsum - lsum + mid_num * (lnum - rnum);
    113             printf("%I64d
    ",ans);
    114         }
    115         printf("
    ");
    116     }
    117     return 0;
    118 }

    主席树部分代码:(主席树会MLE,已经和划分树代码对拍过,应该没问题)

      1 typedef long long ll; 
      2 const int maxn = 1e5+10;
      3 int n,q,tot;
      4 
      5 //主席树部分
      6 int lson[maxn*20],rson[maxn*20],c[maxn*20],tree[maxn];
      7 
      8 ll sum[maxn*20];
      9 int build (int l,int r)
     10 {
     11     int root = tot++;
     12     c[root] = 0;
     13     sum[root] = 0;
     14     if (l != r)
     15     {
     16         int mid = (l + r) >> 1;
     17         lson[root] = build(l,mid);
     18         rson[root] = build(mid+1,r);
     19     }
     20     return root;
     21 }
     22 int update(int root,int pos,int val,int k)
     23 {
     24     int newroot = tot++;
     25     int tmp = newroot;
     26     int l = 1, r = n;
     27     c[newroot] = c[root] + val;
     28     sum[newroot] = sum[root] + k;
     29     while (l < r)
     30     {
     31         int mid = (l + r) >> 1;
     32         if (pos <= mid)
     33         {
     34             rson[newroot] = rson[root];
     35             root = lson[root];
     36             lson[newroot] = tot++;
     37             newroot = lson[newroot];
     38             r = mid;
     39         }
     40         else
     41         {
     42             lson[newroot] = lson[root];
     43             root = rson[root];
     44             rson[newroot] = tot++;
     45             newroot = rson[newroot];
     46             l = mid + 1;
     47         }
     48         c[newroot] = c[root] + val;
     49         sum[newroot] = sum[root] + k;
     50     }
     51     return tmp;
     52 }
     53 ll lsum,rsum;                       //lsum小于中位数的和,rsum大于中位数的和
     54 ll query(int root,int l,int r,int ua,int ub)                  //查询1-root 大于ua小于ub的和
     55 {
     56     if (ub < ua)
     57         return 0;
     58     if (ua <= l && ub >= r)
     59     {
     60         return sum[root];
     61     }
     62     int mid = (l + r) >> 1;
     63     ll t1 = 0,t2 = 0;
     64     if (ua <= mid)
     65         t1 = query(lson[root],l,mid,ua,ub);
     66     if (ub > mid)
     67         t2 = query(rson[root],mid+1,r,ua,ub);
     68     return t1 + t2;
     69 }
     70 int query1(int root,int l,int r,int ua,int ub)               //查询1-root  在ua ub 之间的数的个数
     71 {
     72     if (ub < ua)
     73         return 0;
     74     if (ua <= l && ub >= r)
     75     {
     76         return c[root];
     77     }
     78     int mid = (l + r) >> 1;
     79     int t1 = 0,t2 = 0;
     80     if (ua <= mid)
     81         t1 = query1(lson[root],l,mid,ua,ub);
     82     if (ub > mid)
     83         t2 = query1(rson[root],mid+1,r,ua,ub);
     84     return t1 + t2;
     85 }
     86 int query(int left,int right,int k)                                 //查询left right区间第k大 
     87 {
     88     int l_root = tree[left-1];
     89     int r_root = tree[right];
     90     int l = 1, r = n;
     91     while (l < r)
     92     {
     93         int mid = (l + r) >> 1;
     94         int tmp = c[lson[r_root]] - c[lson[l_root]];
     95         if (tmp <= k)
     96         {
     97             k -= tmp;
     98             r_root = rson[r_root];
     99             l_root = rson[l_root];
    100             l = mid + 1;
    101         }
    102         else
    103         {
    104             l_root = lson[l_root];
    105             r_root = lson[r_root];
    106             r = mid;
    107         }
    108     }
    109     return l;
    110 }
    111 int vec[maxn],rel[maxn],idx;
    112 //离散化
    113 inline void init_hash()
    114 {
    115     sort(vec,vec+idx);
    116     idx = unique(vec,vec+idx) - vec;
    117 }
    118 inline int _hash(ll x)
    119 {
    120     return lower_bound(vec,vec+idx,x) - vec + 1;
    121 }
    122 
    123 
    124 int main(void)
    125 {
    126     #ifndef ONLINE_JUDGE
    127         freopen("in.txt","r",stdin);
    128         freopen("wa.txt","w",stdout);
    129     #endif
    130     int t,cas = 1;
    131     scanf ("%d",&t);
    132     while (t--)
    133     {
    134         memset(sum,0,sizeof(sum));
    135         scanf ("%d",&n);
    136         idx = tot = 0;
    137         for (int i = 1; i<= n; i++)
    138         {
    139             //scanf ("%d",a+i);
    140             scanf ("%d",tree+i);
    141             vec[idx++] = tree[i];
    142         }
    143         init_hash();
    144         tree[0] = build(1,n);
    145         for (int i = 1; i <= n; i++)
    146         {
    147             int tmp = _hash(tree[i]);
    148             rel[tmp] = tree[i];
    149 
    150             tree[i] = update(tree[i-1],tmp,1,tree[i]);
    151             //tree[i] = tmp2;
    152         }
    153         scanf ("%d",&q);
    154         printf("Case #%d:
    ",cas++);
    155         while (q--)
    156         {
    157             int u,v;
    158             scanf ("%d%d",&u,&v);
    159             u++,v++;
    160             int vir_mid = query(u,v,(v-u)/2);
    161             int mid_num = rel[vir_mid];                //中位数
    162             lsum = query(tree[u-1],1,n,1,vir_mid-1);
    163             rsum = query(tree[u-1],1,n,vir_mid+1,n);
    164             ll x1 = lsum, x2 = rsum;
    165 
    166             lsum = query(tree[v],1,n,1,vir_mid-1);
    167             rsum = query(tree[v],1,n,vir_mid+1,n);
    168             int lnum = query1(tree[v],1,n,1,vir_mid - 1) - query1(tree[u-1],1,n,1,vir_mid - 1);
    169             int rnum = query1(tree[v],1,n,vir_mid + 1,n) - query1(tree[u-1],1,n,vir_mid + 1,n);
    170             printf("%I64d
    ",rsum - x2 - (lsum - x1) +  (lnum - rnum) * mid_num);
    171         }
    172         printf("
    ");
    173     }
    174     return 0;
    175 
    176 }
  • 相关阅读:
    18款 非常实用 jquery幻灯片图片切换
    6款强大的 jQuery 网页布局创建及优化插件
    18 个最新实用的 jQuery 插件
    jQuery中的编程范式
    JQuery _ 定时器(jQuery Timers) 学习
    21个最佳jQuery插件推荐
    7 款基于 JavaScript/AJAX 的文件上传插件
    C#
    kernel 3.10内核源码分析--hung task机制
    进程的虚拟地址空间
  • 原文地址:https://www.cnblogs.com/oneshot/p/4127018.html
Copyright © 2011-2022 走看看