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;
    }
    
    
  • 相关阅读:
    文字无缝滚动效果,鼠标移入时暂停
    Spring中使用@Autowired注解静态实例对象
    服务器环境搭建
    nexus问题
    useUnicode=true&characterEncoding=UTF-8 的作用
    SpringBoot项目启动时自动执行指定方法
    springboot自定义消息转换器HttpMessageConverter
    kubernetes资源类别介绍
    红黑树与平衡二叉树的比较
    Feign Client的超时时间
  • 原文地址:https://www.cnblogs.com/mangoyang/p/9314552.html
Copyright © 2011-2022 走看看