hdu 5792 World is Exploding 2016 Multi-University 5

2023-11-16

Problemacm.hdu.edu.cn/showproblem.php?pid=5792

题意:给一个序列 V,问有多少个由下标组成的四元组(a,b,c,d),满足:a != b != c != d,a < b,c < d, Va < Vb,Vc > Vd

分析:可以考虑先把所有顺序数对的个数、逆序数对的个数找出来相乘,然后再去掉不符合下标大小关系的

数据范围是 [ 0,1e9 ],不能直接开这么大的树状数组统计,但是在求顺序数对、逆序数对时,只需要用到元素间的相对大小关系这一个性质,可以把原序列的数改成小的,并保持它们之间的相对大小的关系,不影响答案,而元素个数最多 5万 个,改值后最大不超过50000,就可以用树状数组

可以用一个结构体数组记每一个元素的值、下标,然后升序排序,从小到大把值改成1、2、3…这些,并通过记录的下标把原数列记录的值也改了

先算好4个数组:

ls[ ]:ls[i] 表示 i 左边比 Vi 小的数的个数(left smaller)

lg[ ]:lg[i] 表示 i 左边比 Vi 大的数的个数(left greater)

rs[ ]:……(right smaller)

rg[ ]:……(right greater)

去重的问题:前面说的直接相乘会有多算,情况有:a = c,a = d,b = c,b = d 这4种

a = c 时,b与d同在右侧,但一个比Va小,一个比它大,故 b != d。ans -= rs[ i ] * rg[ i ] (0 <= i < n)

a = d 时,b与c不同侧,ans -= lg[ i ] * rg[ i ]

b = c 时,a与d不同侧,ans -= ls[ i ] * rs[ i ]

b = d 时,a于c同在左侧,一个比Vb小,一个比它大,故a != c。ans -= ls[ i ] * lg[ i ]

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 50000

typedef struct
{
	int v; // 原值
	int id; // 在原数组中的下标
	int nw; // 新值
}node;

node tmp[N]; // 用来排序、改值,并且修改in[]中的值
int bit[N+1];// 树状数组
int in[N]; // 输入的数组
int lg[N],rg[N],ls[N],rs[N];

int cmp(const void *a, const void *b)
{
	node *c = a,*d = b;
	return c->v - d->v;
}

int sum(int x)
{
	int ans;
	for(ans=0; x>0; x-=x&-x)
	  ans += bit[x];
	return ans;
}

void add(int p,int top)
{
	for(;p<=top; p+=p&-p)
	  bit[p]++;
}

int main()
{
	int n,big;
	long long ans;
	long long prels,prers; // ls[]和rs[]的前缀和
	while( ~scanf("%d",&n) )
	{
		int i;
		for(i=0; i<n; i++)
		{
			scanf("%d",in + i);
			tmp[i].v = in[i];
			tmp[i].id = i;
		}
		qsort(tmp, n, sizeof( node ), cmp);
		for(in[ tmp[0].id ] = tmp[0].nw = 1,i=1; i<n; i++) // 最小元素的新值赋1
		  if(tmp[i].v == tmp[i-1].v) // 原值跟前面相等则新值也赋相等的值
		  	in[ tmp[i].id ] = tmp[i].nw = tmp[i-1].nw;
		  else // 否则就是前面的新值+1
		  	in[ tmp[i].id ] = tmp[i].nw = tmp[i-1].nw + 1;
		big = tmp[n-1].nw; // 改值后用到的最大的值
		// 算ls[]和lg[]
		memset(bit,0,sizeof(bit));
		for(i = prels = 0; i<n; i++)
		{
			ls[i] = sum( in[i]-1 );
			lg[i] = sum( big ) - sum( in[i] );
			prels += ls[i];
			add(in[i], big);
		}
		// 算rs[]和rg[]
		memset(bit,0,sizeof(bit));
		for(i=n-1, prers=0; ~i; i--)
		{
			rs[i] = sum( in[i]-1 );
			rg[i] = sum( big ) - sum( in[i] );
			prers += rs[i];
			add(in[i], big);
		}
		// 去重
		for(ans = prels * prers, i=0; i<n; i++)
		{
			ans -= (long long) rs[i] * rg[i]; // a = c
			ans -= (long long) lg[i] * rg[i]; // a = d
			ans -= (long long) ls[i] * rs[i]; // b = c
			ans -= (long long) ls[i] * lg[i]; // b = d
		}
		printf("%I64d\n",ans);
	}
	return 0;
}
参考: blog.csdn.net/libin66/article/details/52098019

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

hdu 5792 World is Exploding 2016 Multi-University 5 的相关文章

  • DispatcherTimer 未按时执行

    我正在使用 c 中的 DispatchTimer 编写一个时钟应用程序 但由于某些原因 我的时钟似乎时不时地跳过 1 秒 例如 52 秒 gt 54 秒 跳过 53 秒 在我看来 计时器并不是每秒都执行一次 DispatcherTimer
  • SetWindowsHookEx 函数返回 NULL

    我正在研究 DLL 注入 但收到错误如下 挂接进程失败 87 参数不正确 目标进程和dll都是64位的 注入代码为 BOOL HookInjection TCHAR target TCHAR dll name https msdn micr
  • 返回 int& 的函数[重复]

    这个问题在这里已经有答案了 我在网上查了一下发现一篇试图解释的文章std move和右值 http thbecker net articles rvalue references section 01 html并发现了一些我实在无法掌握的东
  • 如何使用汇编获取BIOS时间?

    我正在从头开始实现一个小型操作系统 用于教育目的 现在 我想使用汇编来获取 BIOS 时间 我对此进行了很多搜索 但找不到任何代码示例来执行此操作 如果有人可以提供任何参考或代码示例或与此相关的任何内容 我将非常感激 See 时钟中断 1a
  • 如何将字节块读入结构体

    我有一个需要处理的资源文件 它包含一组文件 首先 资源文件列出了其中包含的所有文件 以及一些其他数据 例如在此结构中 struct FileEntry byte Value1 char Filename 12 byte Value2 byt
  • F10键没被抓住

    I have a Windows Form and there overriden ProcessCmdKey However this works with all of the F Keys except for F10 I am tr
  • 在通过网络发送之前压缩位图

    我正在尝试通过网络发送位图屏幕截图 因此我需要在发送之前对其进行压缩 有一个库或方法可以做到这一点吗 当您将图像保存到流时 您have选择一种格式 几乎所有位图格式 bmp gif jpg png 都使用一种或多种压缩形式 因此 只需选择适
  • 特定设备的不同字体大小

    我目前正在开发通用应用程序 我需要分别处理移动设备和桌面的文本框字体大小 我找到了一些方法 但都不能解决问题 使用 VisualStateManager 和 StateTrigger 为例
  • 抽象类或接口。哪种方式是正确的?

    有两种方法可以选择抽象类或接口 微软解决方案和Oracle解决方案 微软 设计指南 请使用抽象 在 Visual Basic 中为 MustInherit 类而不是接口来将协定与实现分离 http msdn microsoft com en
  • 使用scanf()时如何区分整数和字符

    我只是使用该功能scanf 代码如下 scanf d a printf d a 当我输入1时 它会像我想要的那样打印1 但即使我输入 1a 它也会像以前一样打印 1 当用户输入非整数时 例如 2 3 12ab 1 a 我想向用户显示 输入整
  • 线程安全的 C++ 堆栈

    我是 C 新手 正在编写一个多线程应用程序 不同的编写者将对象推入堆栈 读者将它们从堆栈中拉出 或至少将指针推入对象 C 中是否有任何内置结构可以在不添加锁定代码等的情况下处理此问题 如果没有 那么 Boost 库呢 EDIT 你好 感谢您
  • 不要声明只读可变引用类型 - 为什么不呢?

    我一直在阅读这个问题 https stackoverflow com questions 2274412 immutable readonly reference types fxcop violation do not declare r
  • Dynamics Crm:获取状态代码/状态代码映射的元数据

    在 Dynamics CRM 2011 中 在事件实体上 状态原因 选项集 也称为状态代码 与 状态 选项集 也称为状态代码 相关 例如看这个截图 当我使用 API 检索状态原因选项集时 如下所示 RetrieveAttributeRequ
  • C++ 标准中短语“构造函数没有名称”的含义

    在尝试理解 C 标准中的 构造函数没有名称 这句话时 我似乎在 clang 中发现了一个错误 有人可以证实这一点吗 VS2015 and gcc rejects this code and I think they it are is co
  • 将 bignum 类型结构转换为人类可读字符串的有效方法是什么?

    我有一点问题 为了增长我的 C 知识 我决定尝试实现一个基本的 bigint 库 bigint 结构的核心将是一个 32 位整数数组 选择它们是因为它们适合寄存器 这将允许我在数字之间进行操作 这些操作将在 64 位整数中溢出 这也将适合寄
  • 微软语音识别速度

    我正在使用微软的语音识别器开发一个小型练习应用程序 对于我正在做的事情来说 我似乎无法让它足够快地识别单个单词 我希望能够正常说话 系统将从我所说的内容中抓取 关键字 并生成一个字符串 目前我正在使用 5 个单词的自定义语法 红 蓝 黄 绿
  • 程序退出后,TcpListener Socket 仍处于活动状态

    当我的程序退出时 我试图停止 TCP 侦听器 我不关心套接字或任何活动客户端套接字上当前活动的任何数据 套接字清理代码本质上是 try myServer Server Shutdown SocketShutdown Both catch E
  • 创建带有部分的选项卡式侧边栏 WPF

    我正在尝试创建一个带有部分的选项卡式侧边栏 如 WPF 中的以下内容 我考虑过几种方法 但是有没有更简单 更优雅的方法呢 方法一 列表框 Using a ListBox并将 SelectedItem 绑定到右侧内容控件所绑定的值 为了区分标
  • 使用剪贴板 SetText 换行

    如何使用 SetText 方法添加换行符 I tried Clipboard SetText eee n xxxx 但当我将剪贴板数据粘贴到记事本中时 它没有给我预期的结果 预期结果 eee xxxx 我怎样才能做到这一点 Windows
  • 如何从函数返回矩阵(二维数组)? (C)

    我创建了一个生成宾果板的函数 我想返回宾果板 正如我没想到的那样 它不起作用 这是函数 int generateBoard int board N M i j fillNum Boolean exists True initilize se

随机推荐