hdu5792 World is Exploding(多校第五场)树状数组求逆序对 离散化
来源:互联网 发布:建筑设计软件下载 编辑:程序博客网 时间:2024/05/16 15:51
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5792
题目描述:给你n个值,每个值用A[i]表示,然后问你能否找到多少组(a,b,c,d)四个编号,四个编号互不相同,然后a < b, c < d,a代表的值小于b代表的值,c代表的值大于d代表的值。
解题思路:先考虑a和b这两个编号,遍历每一个编号作为b,然后找到b前面有多少个小于b的值,就是对于这一个编号b合理的编号a,对于每一组a和b,就可以考虑c和d,能够满足条件c和d的很显然就是除去a和b整个序列有多少个逆序对,对吧。然后对于每一个b有x个a满足条件,所以对于当前b,能够满足条件的就是(x*所有的逆序对的个数 - 逆序对中包涵a和b的个数)。所有逆序对很容易就可以用树状数组求出来,x也就是b前面有多少个小于编号b代表的值得个数,也很容易求出来,然后包涵a和b个数的逆序对呢,a前面大于A[a]的个数和a后面小于A[a]的个数,b也是一样的。
设x为对于每个b满足条件的a的个数,na代表和a有关系的逆序对,nb代表和b有关系的逆序对,tot代表所有的逆序对个数,然后对于每一个b就有 tot*x - nb*x - (所有na的值)。
代码:
#include<cstdio>#include<cmath>#include<iostream>#include<algorithm>#include<vector>#include<stack>#include<cstring>#include<queue>#include<set>#include<string>#include<map>#define inf 9223372036854775807#define INF 9e7+5#define PI acos(-1)using namespace std;typedef long long ll;typedef double db;const int maxn = 5e4 + 5;const int mod = 1e9 + 7;const db eps = 1e-9;ll n, c[maxn], a[maxn], num[maxn], tot, cc[maxn], lar[maxn], b[maxn];struct pos { ll a, ord, la;} q[maxn];void init() { tot = 0; memset(c, 0, sizeof(c)); memset(cc, 0, sizeof(cc)); memset(lar, 0, sizeof(lar)); //这个数组好像不用初始化}ll lowbit(ll x) { return x & (-x); //求最低位}void updata(ll x, ll p, ll u[]) { //更新 while (x <= maxn) { u[x] += p; x += lowbit(x); }}ll getsum(ll x, ll u[]) { ll ans = 0; while (x > 0) { ans += u[x]; x -= lowbit(x); } return ans;}bool cmp1(const pos&a, const pos&b){ return a.a<b.a;}bool cmp2(const pos&a, const pos&b){ return a.ord<b.ord;}void solve() { while (cin >> n) { init(); for (int i = 1; i <= n; i++) { scanf("%I64d", &q[i].a); q[i].ord = i; } int pp = 0; sort(q+1, q+1+n, cmp1); q[0].a = -1; for (int i = 1; i <= n; i++) { //离散化 if (q[i].a != q[i-1].a) q[i].la = ++pp; else { q[i].la = pp; } } sort(q+1, q+1+n, cmp2); for (int i = 1; i <= n; i++) { lar[i] = i - getsum(q[i].la, c) - 1; //求出每个数前面 updata(q[i].la, 1, c); //有多少比他大的数 } memset(c, 0, sizeof(c)); for (int i = n; i >= 1; i--) { num[i] = getsum(q[i].la-1, c); //求出每个数的 updata(q[i].la, 1, c); tot += num[i]; //后面比他小的个数 } ll ans = 0; memset(c, 0, sizeof(c)); for (int i = 1; i <= n; i++) { ll tmp = getsum(q[i].la-1, c); //对当前b满足条件的a的个数 updata(q[i].la, 1, c); ll tt = getsum(q[i].la-1, cc); //求出和a有关系的逆序对 updata(q[i].la, num[i] + lar[i], cc);//num[i]+lar[i]就是和a有关系的逆序对 ans += tmp * tot - tt - (num[i]+lar[i])*tmp;//这里的num[i]+lar[i]是和b有关系的逆序对 } cout << ans << endl; }}int main(){ //cin.sync_with_stdio(false); //freopen("tt.txt", "r", stdin); //freopen("isharp.out", "w", stdout); solve(); return 0;}
阅读全文
0 0
- hdu5792 World is Exploding(多校第五场)树状数组求逆序对 离散化
- HDU5792(2016多校第五场)——World is Exploding(树状数组,离散化)
- (多校第五场1012)HDU5792 World is Exploding(树状数组)
- hdu5792 多校5 World is Exploding【树状数组求逆序数】
- HDU 5792 World is Exploding (树状数组逆序对)
- HDU5792(离散化+树状数组求逆序数)树状数组求逆序深入讲解
- HDU-5792-World is Exploding(树状数组+离散化)
- HDU 5792 World is Exploding(树状数组+离散化)
- HDU5792 World is Exploding(树状数组)2016 Multi-University Training Contest 5
- 2016 MUT 5 1012 World is Exploding(hdu5792) 【树状数组】
- hdu 5792 World is Exploding 离散化+树状数组
- HDU-5792 World is Exploding(思维、树状数组+离散化)
- hdu5792 World is Exploding
- HDU 5792 World is Exploding (容斥原理+离散化+树状数组)
- HDU 5792 多校5 World is Exploding(树状数组,离散化,组合数学)
- HDU 5792 World is Exploding 2016多校赛第五场 树状数组+容斥原理
- HDU5792 World is Exploding (线段树&&逆序数)
- 树状数组+离散化求逆序对
- 求二叉树叶子节点的个数
- 转载==数论倒数,又称逆元(我整个人都倒了( ̄﹏ ̄))
- HDU 5768Lucky7(多校第四场)容斥+中国剩余定理(扩展欧几里德求逆元的)+快速乘法
- HDU 5778 abs (暴力枚举)
- hdu5739Fantasia(多校第二场1006) 割点+逆元
- hdu5792 World is Exploding(多校第五场)树状数组求逆序对 离散化
- HDU 4281 (状态压缩+背包+MTSP)
- Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest(二月十日训练赛)
- Gym
- 堆的使用,输入数组个数和元素,求平均值
- Gym
- 2015 AlBaath Collegiate Programming Contest(2月14日训练赛)
- hdu 4190 Distributing Ballot Boxes
- gym 100947I (求因子)