zoukankan      html  css  js  c++  java
  • hdu 2838 Cow Sorting (树状数组+逆序对)

    题目

    题意:给你N个排列不规则的数,任务是把它从小到大排好,每次只能交换相邻两个数,交换一次的代价为两数之和,求最小代价

    拿到这道题,我根本看不出这道题和树状数组有半毛钱关系,博客之,全说用树状数组做,纳尼。。。看来我还是太年轻。。

    这道题还涉及到了逆序对,何为逆序对:对于一个包含N个非负整数的数组A[1..n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。

    放到这道题中,如何求代价即:这有N个数,第i个数的代价  =   在i前面大于 i 的数字个数 *  i  + 在 i 前面大于 i 的数字之和。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define N 100001
    int n;
    struct node
    {
    	int cnt;
    	__int64 sum;
    }c[N];
    int lowbit(int x)
    {
    	return x&(-x);
    }
    void update(int x,int s)
    {
    	while(x<=n)
    	{
    		c[x].cnt+=1;
    		c[x].sum+=s;
    		x+=lowbit(x);
    	}
    }
    int getsum_cnt(int x)
    {
    	int ans=0;
    	while(x>0)
    	{
    		ans+=c[x].cnt;
    		x-=lowbit(x);
    	}
    	return ans;
    }
    __int64 getsum_sum(int x)
    {
    	__int64 ans=0;
    	while(x>0)
    	{
    		ans+=c[x].sum;
    		x-=lowbit(x);
    	}
    	return ans;
    }
    int main(void)
    {
    	while(~scanf("%d",&n))
    	{
    		int i;
    		__int64 ans=0;
    		memset(c,0,sizeof(c));
    		for(i=1;i<=n;i++)
    		{
    			int x;
    			scanf("%d",&x);
    			update(x,x);
    			__int64 k1=i-getsum_cnt(x);
    			//getsum_cnt(x)是小于等于x的数字的个数,i-getsum_cnt(x)就是大于x的数字的个数
    			if(k1!=0)
    			{
    				__int64 k2=getsum_sum(n)-getsum_sum(x);//[x+1,n]区间的数字值和,即[1,n]-[1,x]
    				ans=ans+k1*x+k2;
    			}
    
    		}
    		printf("%I64d
    ",ans);
    	}
    }
    
  • 相关阅读:
    [luogu p2482] [SDOI2010]猪国杀
    [luogu p2296] 寻找道路
    左右布局(备用复制)
    导出Excel
    流式布局 及 媒体查询
    echarts设置(持续更新)
    解决Vue中watch首次进入路由不触发的问题
    Math.random
    Vue的拖拽
    使的dialog上下左右居中(弹框居中)
  • 原文地址:https://www.cnblogs.com/qie-wei/p/10160181.html
Copyright © 2011-2022 走看看