zoukankan      html  css  js  c++  java
  • 「LGR-049」洛谷7月月赛 D.Beautiful Pair

    [「LGR-049」洛谷7月月赛 D.Beautiful Pair](https://www.luogu.org/problemnew/show/P4755)

    题目大意 : 给出长度为 (n) 的序列,求满足 (i leq j) 且 $a_i imes a_j leq max(a_i..a_j) $ 的点对((i, j))的数量
    (n leq 10^5 1 leq a_i leq 10^9)

    解题思路 :

    直接枚举某一端点貌似很难维护极值,不妨对于每一个极值 (a_k),求 $ max(a_i..a_j) leq a_k$ 且 (i leq k leq j) 的点对数
    考虑一个每一个点能作为(max)统治的区间可以用单调栈求,并构建出笛卡尔树

    此时对于每一个 (a_k) 答案由两部分产生:

    1. 点对 ((i, j)) 满足 (i = k) 或 $j = k $,这一部分答案比较简单,就是统治区间内 (1) 的个数
    2. 点对 ((i, j)) 满足 (i eq k)(j eq k) ,此时答案等价于点 (k) 在笛卡尔树上的节点的左右子树中各取一个组成合法点对的方案数

    第一种情况可以直接前缀和计算,在此不多做讨论,主要看第二种情况

    由于是树上的子树问题,我们很容易想到用 (dsu on tree) 的做法来解决

    不了解 (dsu on tree) 的可以戳这里的链接

    枚举子树大小较小的子树,用树状数组维护较大的子树产生的贡献

    对于较小子树中的点 (u) ,能与其组成合法点对的点 (x) 要满足 (frac{maxval}{a_u} leq a_x),直接用树状数组统计前缀和即可


    /*program by mangoyang*/
    #include<bits/stdc++.h>
    #define inf (0x7f7f7f7f)
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
        int f = 0, ch = 0; x = 0;
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
        for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        if(f) x = -x;
    }
    #define N (500005)
    #define int ll
    int a[N], b[N], n, ans;
    namespace Ls{
    	int s[N]; int lens = 0;
    	inline int calc(int x){
    		int res = upper_bound(s + 1, s + lens + 1, x) - s - 1;
    		return res;
    	}
    	inline void Realmain(){
    		for(int i = 1; i <= n; i++) s[i] = a[i];
    		sort(s + 1, s + n + 1);
    		lens = unique(s + 1, s + n + 1) - s - 1;
    	}
    }
    struct Fenwick{
    	int s[N];
    	inline int lowbit(int x){ return x & -x; }
    	inline void add(int x, int v){
    		for(int i = x; i <= n; i += lowbit(i)) s[i] += v;
    	}
    	inline int query(int x){
    		int ans = 0;
    		for(int i = x; i; i -= lowbit(i)) ans += s[i];
    		return ans;
    	}
    }Bit;
    namespace Treap{
    	int sz[N], ch[N][2], s[N], l[N], r[N], st[N], top;
    	inline void Getsize(int u){
    		sz[u] = 1; 
    		int ls = ch[u][0], rs = ch[u][1];
    		if(ls) Getsize(ls), sz[u] += sz[ls];
    		if(rs) Getsize(rs), sz[u] += sz[rs];
    		if(!u) sz[u] = 0;
    	}
    	inline void Add(int u){
    		Bit.add(b[u], 1);
    		if(ch[u][0]) Add(ch[u][0]);
    		if(ch[u][1]) Add(ch[u][1]);
    	}
    	inline void Clear(int u){
    		Bit.add(b[u], -1);
    		if(ch[u][0]) Clear(ch[u][0]);
    		if(ch[u][1]) Clear(ch[u][1]);
    	}
    	inline int Count(int u, int val){
    		int pos = Ls::calc(val / a[u]);
    		int res = Bit.query(pos);
    		if(ch[u][0]) res += Count(ch[u][0], val);
    		if(ch[u][1]) res += Count(ch[u][1], val);
    		return res;
    	}
    	inline void solve(int u){
    		int p = sz[ch[u][0]] > sz[ch[u][1]] ? 0 : 1;
    		int ms = ch[u][p], ls = ch[u][p^1];
    		if(ls) solve(ls), Clear(ls);
    		if(ms) solve(ms); 
    		if(ls) ans += Count(ls, a[u]);
    		if(u){ if(ls) Add(ls); Bit.add(b[u], 1); } 
    	}
    	inline void Build(){
    		for(int i = 1; i <= n; i++){
    			while(a[st[top]] <= a[i] && top) r[st[top--]] = i - 1;
    			int f = st[top]; l[i] = f + 1;
    			ch[i][0] = ch[f][1], ch[f][1] = i, st[++top] = i; 
    		}
    		for(int i = 1; i <= n; i++) if(!r[i]) r[i] = n;
    	}
    	inline void Realmain(){
    		Build(), Getsize(0), solve(0);
    		for(int i = 1; i <= n; i++) s[i] = s[i-1] + (a[i] == 1 ? 1 : 0);
    		for(int i = 1; i <= n; i++) ans += s[r[i]] - s[l[i]-1];
    		cout << ans << endl;
    	}
    }
    main(){
    	read(n);
    	for(int i = 1; i <= n; i++) read(a[i]);
    	Ls::Realmain();
    	for(int i = 1; i <= n; i++) b[i] = Ls::calc(a[i]);
    	Treap::Realmain();
    	return 0;
    }
    
    
  • 相关阅读:
    WinRAR v5.90中文正式32&64位整合安装版
    WIN10永久激活工具 HWIDGEN
    Adobe2020套装激活工具
    keka 1.1.26-压缩工具
    python文件和目录操作方法大全(含实例)
    如何使公网能够访问本地web服务器?
    网线那根正极那根负极
    HPUX 大文件系统扩容
    LESS详解之函数(四)
    Win7 安装Apache 2.2.4报错:<OS 5>拒绝访问. :Failed to open the WinNT service manager
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9314552.html
Copyright © 2011-2022 走看看