zoukankan      html  css  js  c++  java
  • HDU2491 Priest John's Busiest Day

    题目链接

    题意:

    有n个人要进行乒乓球比赛,每一个人都一个能力值。每一个人出现的次序就是他们住的位置

    如今要求进行一场比赛,三个人,裁判的能力值在两个选手之间,住的位置也在两个人的之间

    问这样的比赛一共能够进行多少次

    思路:

    用树状数组做,否则TLE,先从左到右扫一遍,计算每点左边大的个数和小的个数,

    再从右到左扫一遍,计算每点右边大和小的个数,然后交叉相乘取和就能够了

    代码例如以下:

    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+10;
    int n;
    int p[N], c[N], li[N], la[N], ri[N], ra[N];
    
    inline int Lowbit(int x){ return x&(-x); } 
    
    void change(int u, int x)
    {
    	while(u < N)
    	{
    		c[u] += x;
    		u += Lowbit(u);
    	}
    } 
    
    int get_sum(int x)
    {
    	int ans = 0;
    	for(int i = x; i > 0; i -= Lowbit(i))
    	{
    		ans += c[i];
    	}
    	return ans;
    }
    
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t--)
    	{
    		memset(c, 0, sizeof(c));
    		scanf("%d", &n);
    		for(int i = 1; i <= n; i++)
    		{
    			scanf("%d", &p[i]);
    			int cnt = get_sum(p[i]);
    			li[i] = cnt; // i点左边比它小的 
    			la[i] = i - cnt - 1; //i点左边比它大的 
    			change(p[i], 1);
    		}
    		memset(c, 0, sizeof(c));
    		for(int i = n; i > 0; i--)
    		{
    			int cnt = get_sum(p[i]);
    			ri[i] = cnt; // i点右边比它小的 
    			ra[i] = n - i - cnt; //i点右边比它大的 
    			change(p[i], 1); 
    		}
    		ll ans = 0;
    		for(int i = 1; i <= n; i++)
    		{
    			ans += li[i] * ra[i] + la[i] * ri[i];
    		}
    		printf("%I64d
    ", ans);
    	}
    	return 0;
    }
    


  • 相关阅读:
    spark发现新词
    树的算法总结
    机器学习树的算法总结
    Spark Streaming实例
    ubuntu上通用解压方式
    论MYSQL数据库数据错误的处理
    macOS Sierra上Opencv的安装与使用
    phpstudy2016 redis扩展 windows
    细说PHP7
    正则表达式与.htaccess的配置
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7269741.html
Copyright © 2011-2022 走看看