zoukankan      html  css  js  c++  java
  • [P1637] 三元上升子序列 (线段树+离散化)

    【原题】

    题目描述

    Erwin 最近对一种叫 thair 的东西巨感兴趣。。。

    在含有 nnn 个整数的序列 (a1,a2,…,an) 中,三个数被称作thair当且仅当 (i<j<k)(ai<aj<ak)

    求一个序列中 thair 的个数。

    输入格式

    开始一行一个正整数(n),

    以后一行 (n) 个整数 (a1,a2,…,an)

    输出格式

    一行一个整数表示 thair 的个数。

    输入输出样例

    输入 #1

    4
    2 1 3 4
    

    输出 #1

    2
    

    输入 #2

    5
    1 2 2 3 4
    

    输出 #2

    7
    

    说明/提示

    样例2 解释

    7个 thair 分别是:

    • 1 2 3
    • 1 2 4
    • 1 2 3
    • 1 2 4
    • 1 3 4
    • 2 3 4
    • 2 3 4

    数据规模与约定

    • 对于 (30\%)的数据 保证 (n≤100)
    • 对于 (60\%) 的数据 保证 (n≤2000)
    • 对于 (100\%)的数据 保证 (1≤n≤3×10^4,0≤ai<2^{63})

    【思路】

    用pair存二元个数, cnt存一元个数,不断更新,题解的乘法原理没想到,惭愧。

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <list>
    #include <map>
    #include <iostream>
    #include <iomanip>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <unordered_map>
    #include <vector>
    #define LL long long
    #define inf 0x3f3f3f3f
    #define INF 0x3f3f3f3f3f3f
    #define PI 3.1415926535898
    #define F first
    #define S second
    #define endl '
    '
    #define lson  rt << 1
    #define rson  rt << 1 | 1
    #define f(x, y, z) for (int x = (y), __ = (z); x < __; ++x)
    #define _rep(i, a, b) for (int i = (a); i <= (b); ++i)
    using namespace std;
    
    const int maxn = 3e4 + 7;
    const int maxm = 1e6 + 7;
    const int mod = 1e9 + 7;
    int n, m;
    
    struct node
    {
    	LL pair, cnt;
    }tree[maxn * 4];
    
    struct pp
    {
    	LL pair, cnt;
    }lz[maxn * 4];
    
    LL a[maxn], b[maxn], id[maxn];
    
    void update(int n, int index, int L, int R, int rt) {
    	if (L == R) {
    		tree[rt].cnt = n;
    		return;
    	}
    	int mid = (L + R) / 2;
    	if (index <= mid) {
    		update(n, index, L, mid, lson);
    	}
    	else {
    		update(n, index, mid + 1, R, rson);
    	}
    	tree[rt].cnt = tree[lson].cnt + tree[rson].cnt;
    }
    
    void add(int n, int index, int L, int R, int rt)
    {
    	if (L == R)
    	{
    		tree[rt].cnt += n;
    		return;
    	}
    	int mid = (L + R) / 2;
    	if (index <= mid) add(n, index, L, mid, lson);
    	else add(n, index, mid + 1, R, rson);
    	tree[rt].cnt = tree[lson].cnt + tree[rson].cnt;
    }
    
    void push_down(int rt, int l, int r) {
    	if (lz[rt].cnt) {
    		int mid = (l + r) / 2;
    		lz[lson].cnt += lz[rt].cnt;
    		lz[rson].cnt += lz[rt].cnt;
    		tree[lson].cnt += 1LL * (mid - l + 1) * lz[rt].cnt;
    		tree[rson].cnt += 1LL * (r - mid) * lz[rt].cnt;
    		lz[rt].cnt = 0;
    	}
    	if (lz[rt].pair)
    	{
    		int mid = (l + r) / 2;
    		lz[lson].pair += lz[rt].pair;
    		lz[rson].pair += lz[rt].pair;
    		tree[lson].pair += 1LL * (mid - l + 1) * lz[rt].pair;
    		tree[rson].pair += 1LL * (r - mid) * lz[rt].pair;
    		lz[rt].pair = 0;
    	}
    }
    
    LL query_range(int rt, int l, int r, int L, int R) {
    	if (l <= L && r >= R) return tree[rt].cnt;
    	push_down(rt, L, R);
    	int mid = (L + R) / 2;
    	LL sum = 0;
    	if (mid >= l) sum += query_range(lson, l, r, L, mid);
    	if (mid < r) sum += query_range(rson, l, r, mid + 1, R);
    	return sum;
    }
    void add_pair(int n, int index, int L, int R, int rt)
    {
    	if (L == R)
    	{
    		tree[rt].pair += n;
    		return;
    	}
    	int mid = (L + R) / 2;
    	if (index <= mid) add_pair(n, index, L, mid, lson);
    	else add_pair(n, index, mid + 1, R, rson);
    	tree[rt].pair = tree[lson].pair + tree[rson].pair;
    }
    
    LL query_pair(int rt, int l, int r, int L, int R)
    {
    	if (l <= L && r >= R) return tree[rt].pair;
    	push_down(rt, L, R);
    	int mid = (L + R) / 2;
    	LL sum = 0;
    	if (mid >= l) sum += query_pair(lson, l, r, L, mid);
    	if (mid < r) sum += query_pair(rson, l, r, mid + 1, R);
    	return sum;
    }
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    	cin >> n;
    	LL ans = 0;
    	int mx = 3e4;
    	_rep(i, 1, n)
    	{
    		cin >> a[i];
    		b[i] = a[i];
    	}
    	sort(a + 1, a + n + 1);
    	int sz = unique(a + 1, a + n + 1) - a - 1;
    	mx = sz + 1;
    	_rep(i, 1, n)
    	{
    		id[i] = lower_bound(a + 1, a + 1 + sz, b[i]) - a;
    	}
    	_rep(i, 1, n)
    	{
    		add(1, id[i], 0, mx, 1);
    		ans += query_pair(1, 0, id[i] - 1, 0, mx);
    		LL tmp = query_range(1, 0, id[i] - 1, 0, mx);
    		add_pair(tmp, id[i], 0, mx, 1);
    	}
    	cout << ans << endl;
    }
    
  • 相关阅读:
    获得客户端的信息
    JavaScript--垃圾回收器
    JavaScript--函数-按值传递
    JavaScript--声明提前
    JavaScript--函数-01
    JavaScript--赋值表达式(typeof-delete-void)
    JavaScript—赋值表达式-1
    JavaScript--机选双色球
    正则表达式的预判
    自定义比较器函数
  • 原文地址:https://www.cnblogs.com/hfcdyp/p/13436907.html
Copyright © 2011-2022 走看看