A. Tokitsukaze and Strange Inequality(前缀和+桶)

Problem - 1677A - Codeforces

 

时津风有一个长度为n的排列组合p。回顾一下,长度为n的排列组合p是由n个不同的整数组成的序列p1,p2,...,pn,每个整数从1到n(1≤pi≤n)。

她想知道在这个排列组合中,有多少个不同的指数图组[a,b,c,d](1≤a<b<c<d≤n)满足以下两个不等式。

pa<pc和pb>pd。
请注意,如果a1≠a2或b1≠b2或c1≠c2或d1≠d2,两个图元[a1,b1,c1,d1]被认为是不同的。

输入
第一行包含一个整数t(1≤t≤1000)--测试案例的数量。每个测试用例由两行组成。

第一行包含一个整数n(4≤n≤5000)--包络的长度p。

第二行包含n个整数p1,p2,...,pn(1≤pi≤n)--包络p。

保证所有测试案例的n之和不超过5000。

输出
对于每个测试案例,打印一个整数--不同的[a,b,c,d]图组的数量。

例子
输入复制
3
6
5 3 6 1 4 2
4
1 2 3 4
10
5 1 6 2 8 3 4 10 9 7
输出拷贝
3
0
28
注意
在第一个测试案例中,有3个不同的[a,b,c,d]图组。

p1=5, p2=3, p3=6, p4=1,其中p1<p3,p2>p4满足不等式,所以[a,b,c,d]图组中的一个是[1,2,3,4]。

同样地,另外两个图元是[1,2,3,6],[2,3,5,6]。

题解:
我们可以枚举b,过程中,利用桶排的思想把对b前面的数标记,利用前缀和,找到,b后面的数c有多少个是大于a的res,然后在内部循环,c后面的数,找到大于当前b的加上,然后更新res,因为b后面的数可以成为d,也可以为c

(说的有点乱,具体代码有体现)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define int long long
//1 1 3 3 3
int n,ans;
int a[200050];
int tong[5005];
int d[5005];
void solve()
{
	int n;
	cin >> n;
	for(int i = 1;i <= n;i++)
	cin >> a[i],tong[i] = 0;
	int ans = 0,res;
	for(int i = 2;i < n-1;i++)(枚举b的位置)
	{
		tong[a[i-1]]++;(对a的位置进行桶排标记)
		for(int j = 1;j <= n;j++)
		{
		    d[j] = d[j-1] + tong[j];(统计每个位置大于前面的有几个数)
		}
		res = d[a[i+1]];//得到c大于a的个数
		for(int j = i+2;j <= n; j++)//枚举d
		{
			if(a[i] > a[j])//如果b > d
			{
				ans += res;
			}
			res += d[a[j]];//更新res如果a[j]前面有数,说明这个数也可以a[j]也可以为c
		}
	}
	cout<<ans<<"\n";
}
signed main()
{
	int t = 1;
	cin >> t;
	while(t--)
	{
		solve();
	}
}
//2 5
//3
//9 7 


//2  3 4 3
//1 2 3 4 5
//      3

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值