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);
    	}
    }
    
  • 相关阅读:
    iOS中Zbar二维码扫描的使用
    SOJ 1135. 飞跃原野
    SOJ 1048.Inverso
    SOJ 1219. 新红黑树
    SOJ 1171. The Game of Efil
    SOJ 1180. Pasting Strings
    1215. 脱离地牢
    1317. Sudoku
    SOJ 1119. Factstone Benchmark
    soj 1099. Packing Passengers
  • 原文地址:https://www.cnblogs.com/qie-wei/p/10160181.html
Copyright © 2011-2022 走看看