爆裂吧世界(world)
2016-08-06 17:23
281 查看
爆裂吧世界(world/1S/64M)
【题目描述】
给你一个长度为n的数列A,请你计算里面有多少个四元组(a,b,c,d)满足:
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad
【输入格式】
输入文件第一行有一个整数N,第二行有N个整数A1,A2⋯An
【输出格式】
输出文件仅一行,为一个整数,表示满足条件的四元组的数量
【输入1】
4
2 4 1 3
【输出1】
1
【输入2】
4
1 2 3 4
【输出2】
0
【数据约定】
15% n<=100
100%n<=50000
A在int范围里
【解题思路】
15分解法:O(n^4)暴力
100分解法:离散化+树状数组+容斥原理+乘法原理
其实,这一题与树状数组求逆序对差不多。首先,求出符合(a,b)与(c,d)的对数,根据乘法原理,再相乘。但要注意a,b,c,d互不相等。所以要分情况。
不可能:a=b,c=d 因为a<b&&c>d;
第1种:a=c small_left * small_right
第2种:a=d small_left * big_left
第3种:b=c big_right * small_right
第4种:b=d big_left *big_right
所以,只要减去这四种重复的情况就可以了。(注意用long long)
【程序】
【题目描述】
给你一个长度为n的数列A,请你计算里面有多少个四元组(a,b,c,d)满足:
a≠b≠c≠d,1≤a<b≤n,1≤c<d≤n,Aa<Ab,Ac>Ad
【输入格式】
输入文件第一行有一个整数N,第二行有N个整数A1,A2⋯An
【输出格式】
输出文件仅一行,为一个整数,表示满足条件的四元组的数量
【输入1】
4
2 4 1 3
【输出1】
1
【输入2】
4
1 2 3 4
【输出2】
0
【数据约定】
15% n<=100
100%n<=50000
A在int范围里
【解题思路】
15分解法:O(n^4)暴力
100分解法:离散化+树状数组+容斥原理+乘法原理
其实,这一题与树状数组求逆序对差不多。首先,求出符合(a,b)与(c,d)的对数,根据乘法原理,再相乘。但要注意a,b,c,d互不相等。所以要分情况。
不可能:a=b,c=d 因为a<b&&c>d;
第1种:a=c small_left * small_right
第2种:a=d small_left * big_left
第3种:b=c big_right * small_right
第4种:b=d big_left *big_right
所以,只要减去这四种重复的情况就可以了。(注意用long long)
【程序】
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int Maxn = 50010; int n; #define down(a) for(int i=1;i<=n/2;i++) swap(a[i],a[n-i+1]); #define lowbit(x) x & -x struct Tnode{ int x,y; }b[Maxn]; int a[Maxn]; int tr[Maxn]; int bl[Maxn] , br[Maxn] , sl[Maxn] , sr[Maxn]; bool cmp(Tnode x,Tnode y) { return x.x < y.x; } LL Sum(int x) { int sum = 0; for( ;x;x-=lowbit(x)) sum += tr[x]; return sum; } void Add(int x) { for( ;x<=n;x+=lowbit(x)) tr[x] ++; } int main() { freopen("world.in","r",stdin); freopen("world.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&b[i].x); b[i].y = i; } sort(b+1,b+n+1,cmp); int tt = 0; for(int i=1;i<=n;i++) { if(i!=1 && b[i].x == b[i-1].x) tt--; tt++; a[b[i].y] = tt; } for(int i=1;i<=n;i++) { sl[i] = Sum(a[i]-1); bl[i] = Sum(n) - Sum(a[i]); Add(a[i]); } down(a); memset(tr,0,sizeof(tr)); for(int i=1;i<=n;i++) { sr[i] = Sum(a[i]-1); br[i] = Sum(n) - Sum(a[i]); Add(a[i]); } down(sr); down(br); LL ab = 0 , cd = 0 , rc = 0; for(int i=1;i<=n;i++) { ab += sl[i]; cd += bl[i]; rc += sl[i] * sr[i] + sl[i] * bl[i] + br[i] * sr[i] + bl[i] * br[i] ; } LL ans = ab * cd - rc; printf("%I64d",ans); return 0; }
相关文章推荐
- 世界各国及地区纸币 World paper currency
- The World is Flat 世界是平坦的
- Trade and the world economy -- 贸易与世界经济
- 第10章 世界(World Class)
- If the world were a Village of 100 People 如果世界是个一百人的村落
- Love the World——热爱世界
- 明天Around The World 2012(风靡世界2012)发布会 将发布绿叶清泉团队Logo
- Unity中构建现实世界中的地形(插件 World Composer)
- 灰度世界算法(Gray World Algorithm)
- 统治我们世界的十大真实算法(The real 10 algorithms that dominate our world)
- Unity3D 渲染物体世界坐标 WorldPosition Shader
- 威廉·布莱克《从一颗沙子看世界》(To see a world in a grain of sand)
- 爆裂吧世界(world/1S/64M)
- Box2D v2.1.0用户手册翻译 - 第10章 世界(World Class)
- 潘多拉的世界 The World of Pandora
- convertToWorldSpace转换为世界坐标系用法
- Leave The World Behind,将世界抛诸脑后
- 灰度世界算法(Gray World Algorithm) 分类: 图像处理 Matlab 2014-12-07 18:40 874人阅读 评论(0) 收藏
- 灰度世界算法(Gray World Algorithm)和White Patch Retinex算法
- 灰度世界算法(Gray World Algorithm)