hdu1394~线段树求和

开始做题目有一个很重要的条件没注意,做的我相当的苦逼,看了别人的思路,都说很简单。
我却完全不懂,当时想死的心情都有了。不过在队友的提醒下才恍然大悟,原来A数组的值是确定的。
然后去想就感觉理应如此了,先前没看懂的时候写了个暴力代码水过,看清题目后用线段树写速度真不是盖的。

暴力代码:


#include<stdio.h>
#include<iostream>
#define Min(a,b) a<b?a:b
using namespace std;

const int size=5000; 

__int64 ans,minx; 
int a[size+10],up[size+10],down[size+10];


int main()
{
    int i,j,n,sum,minx;
    while (~scanf("%d",&n))
    {
          memset(down,0,sizeof(down));
          memset(up,0,sizeof(up));
          for (i=sum=0;i<n;i++) 
          {
              scanf("%d",a+i);
              for (j=0;j<i;j++)
              {
                  if (a[j]<a[i]) up[j]++,down[i]++;
                  if (a[j]>a[i]) sum++,up[i]++,down[j]++; 
              } 
          }    
          for (minx=sum,i=0;i<n;i++)
          {
              sum=sum-down[i]+up[i];
              minx=Min(minx,sum);
          }
          printf("%d\n",minx);
    }
    return 0;  
} 

线段树代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#define Min(a,b) a<b?a:b
using namespace std;

const int size=5000;
int sum[size<<2],arr[size+10];

void push(int rt)
{
     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

void update(int l,int r,int k,int rt)
{
     if (l==r)
     {
        sum[rt]++;      
        return ;    
     }     
     int mid=(l+r)>>1;
     if (k<=mid) update(l,mid,k,rt<<1);
     else update(mid+1,r,k,rt<<1|1);
     push(rt);
}

int query(int l,int r,int a,int b,int rt)
{
    if (a<=l&&b>=r) return sum[rt];
    int mid=(l+r)>>1,r1=0,r2=0;
    if (a<=mid) r1=query(l,mid,a,b,rt<<1);
    if (b>mid)  r2=query(mid+1,r,a,b,rt<<1|1);  
    return r1+r2;
}

int main()
{
    int i,k,n,sumx,minx;
    while (~scanf("%d",&n))
    {
          memset(sum,0,sizeof(sum));
          for (i=sumx=0;i<n;i++)
          {
              scanf("%d",arr+i);
              sumx+=query(0,n-1,arr[i]+1,n-1,1);
              update(0,n-1,arr[i],1);
          }  
          for (minx=sumx,i=0;i<n-1;i++)
          {
             // printf("minx=%d\n",minx);
              sumx+=n-1-arr[i]-arr[i];
              minx=Min(sumx,minx);
          }  
          printf("%d\n",minx);
    }
    return 0;  
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值