zoukankan      html  css  js  c++  java
  • hdu 3473 Minimum Sum

    题意:给出n个数x1,x2...xn.进行m次操作,每次给出一个区间[l ,r].求出xi属于区间[l, r]使得该区间的每个数与xi的差之和最小,并求出该和。

    思路:划分树。

    View Code
      1 #include <cstdio>
      2 #include <algorithm>
      3 using namespace std;
      4 #define lson l,m,rt+1
      5 #define rson m+1,r,rt+1
      6 #define maxn 100001
      7 struct node
      8 {
      9     int val[maxn];
     10     int num[maxn];
     11     __int64 sum[maxn];
     12 }setree[18];
     13 int sorted[maxn];
     14 __int64 ans[maxn],sum;
     15 void build(int l,int r,int rt)
     16 {
     17     if(l==r)
     18     return ;
     19     int m=(l+r)>>1;
     20     int isame=m-l+1,same=0;
     21     int ln=l,rn=m+1;
     22     for(int i=l;i<=r;i++)
     23     if(setree[rt].val[i]<sorted[m])
     24     isame--;
     25     for(int i=l;i<=r;i++){
     26         if(i==l){
     27         setree[rt].num[i]=0;
     28         setree[rt].sum[i]=0;
     29         }
     30         else{
     31         setree[rt].num[i]=setree[rt].num[i-1];
     32         setree[rt].sum[i]=setree[rt].sum[i-1];
     33         }
     34         if(setree[rt].val[i]<sorted[m]){
     35             setree[rt].num[i]++;
     36             setree[rt].sum[i]+=setree[rt].val[i];
     37             setree[rt+1].val[ln++]=setree[rt].val[i];
     38         }
     39         else if(setree[rt].val[i]>sorted[m])
     40             setree[rt+1].val[rn++]=setree[rt].val[i];
     41         else{
     42             if(same<isame){
     43                 same++;
     44                 setree[rt].num[i]++;
     45                 setree[rt].sum[i]+=setree[rt].val[i];
     46                 setree[rt+1].val[ln++]=setree[rt].val[i];
     47             }
     48             else
     49                 setree[rt+1].val[rn++]=setree[rt].val[i];
     50         }    
     51     }
     52     build(lson);
     53     build(rson);
     54 }
     55 __int64 query(int l,int r,int rt,int L,int R,int k)
     56 {
     57     if(L==R)
     58     return setree[rt].val[L];
     59     int m=(l+r)>>1;
     60     int enterleft1,enterleft2,enterright1,enterright2;
     61     __int64 ss;
     62     if(L==l){
     63         enterleft1=0;
     64         enterleft2=setree[rt].num[R];
     65         enterright1=0;
     66         enterright2=R-l+1-setree[rt].num[R];
     67         ss=setree[rt].sum[R];
     68     }
     69     else{
     70         enterleft1=setree[rt].num[L-1];
     71         enterleft2=setree[rt].num[R];
     72         enterright1=L-l-setree[rt].num[L-1];
     73         enterright2=R-l+1-setree[rt].num[R];
     74         ss=setree[rt].sum[R]-setree[rt].sum[L-1];
     75     }
     76     int temp=enterleft2-enterleft1;
     77     if(temp>=k)
     78     return query(lson,l+enterleft1,l+enterleft2-1,k);
     79     else{
     80         sum+=ss;
     81     return query(rson,m+enterright1+1,m+enterright2,k-temp);
     82     }
     83 }
     84 int main()
     85 {
     86     int t;
     87     scanf("%d",&t);
     88     int cas=1;
     89     while(t--){
     90         int n,m;
     91         scanf("%d",&n);
     92         for(int i=0;i<n;i++){
     93             scanf("%d",&setree[0].val[i]);
     94             sorted[i]=setree[0].val[i];
     95             if(i==0)
     96             ans[i]=setree[0].val[i];
     97             else
     98             ans[i]=ans[i-1]+setree[0].val[i];
     99         }
    100         sort(sorted,sorted+n);
    101         build(0,n-1,0);
    102         scanf("%d",&m);
    103         printf("Case #%d:\n",cas++);
    104         while(m--){
    105             int l,r,k;
    106             scanf("%d%d",&l,&r);
    107             k=(r-l+2)/2;
    108             sum=0;
    109             __int64 temp=query(0,n-1,0,l,r,k);
    110             __int64 sum1=ans[r]-ans[l-1]-sum;
    111             printf("%I64d\n",sum1-sum-(r-l+2-k)*temp+(k-1)*temp);
    112         }
    113         printf("\n");
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    C#发送邮件简单例子
    ABAP随笔
    日期格式转换
    正则校验金额,整数8位,小数3位。
    angular语法运用技巧
    Oracle中连接与加号(+)的使用
    含有代码分析的面试题
    面试的java题目
    递归查询
    本地没有ORACLE远程登录oracle服务器
  • 原文地址:https://www.cnblogs.com/kim888168/p/2810122.html
Copyright © 2011-2022 走看看