zoukankan      html  css  js  c++  java
  • 连续值域区间个数(经典题)

    连续值域区间个数(经典题)

    题目大意

    RT,求一个排列的连续值域区间个数

    数据范围

    (1 le n le 10^5)

    解题思路

    题目描述这么短说明它是一个经典题(也指我不会的那种题)

    连续值域区间的性质 (max - min + 1 = len)(max-min-r+l)

    对于任意一个区间,总有 (max - min - 1 ge len)

    有了这两点性质就可以用单调栈和线段树来做了

    具体来说,两个单调栈分别维护最大最小值,线段树维护最小值(val = max - min)及最小值个数

    每加一个数进来要整体减一表示 r++,查询当前最小值是否为 0 和其个数即可

    代码没必要了

    update:补一个不用单调栈的做法

    不用单调栈啊,你将 (i)(i + 1,i-1) 连边,那么有 ([l,r]) 生产子图边数 = (r-l)

    像上面一样直接线段树即可

    update:补一个 cdq 做法

    考虑跨过中点的连续值域区间个数,先考虑一种情况,对右边取前缀最大值和前缀最小值,使用桶和队列维护,具体来说,我们强制最小值在左边,最大值在右边,同理我们将序列反过来再跑一遍。另外单独考虑最大值最小值在同一侧的情况

    这个给个代码,但不是我的,详见这里

    namespace task60 {
    	int sl[N], sr[N], mn[N], mx[N], cnt[N]; ll ans;
    	
    	void work(int *a, int *b) {
    		int la = a[0], lb = b[0];
    		mn[lb + 1] = 0;
    		for (int i = 1; i <= lb; i++)
    			mn[i] = min(mn[i - 1], b[i]), mx[i] = max(mx[i - 1], b[i]);
    		int curmn = inf, curmx = 0, tl = 1, tr = 1;
    		for (int i = 1; i <= la; i++) {
    			curmn = min(curmn, a[i]), curmx = max(curmx, a[i]);
    			int tmp = curmx - curmn + 1 - i;
    			if (tmp > 0 && tmp <= lb && mn[tmp] > curmn && mx[tmp] < curmx) ans++;
    			while (mn[tr] > curmn) cnt[mx[tr] - tr]++, tr++;
    			while (tl < tr && mx[tl] < curmx) cnt[mx[tl] - tl]--, tl++;
    			ans += (ll)cnt[curmn + i - 1];
    		}
    		for (int i = tl; i < tr; i++) cnt[mx[i] - i] = 0;
    	}
    	void cdq(int l, int r) {
    		if (l == r) { ans++; return; }
    		int mid = (l + r) >> 1;
    		sl[0] = mid - l + 1, sr[0] = r - mid;
    		for (int i = mid; i >= l; i--) sl[mid - i + 1] = p[i];
    		for (int i = mid + 1; i <= r; i++) sr[i - mid] = p[i];
    		work(sl, sr), work(sr, sl);
    		cdq(l, mid), cdq(mid + 1, r);
    	}
    	void sol() {
    		mn[0] = inf, cdq(1, n);
    		printf("%lld
    ", ans);
    		for (int i = 1; i <= n; i++) printf("%d%c", p[i], " 
    " [i == n]);
    	}
    }
    
  • 相关阅读:
    解决ecshop进入后台服务器出现500的问题
    Java8新特性(拉姆达表达式lambda)
    使用Optional优雅处理null
    Arrays.asList 存在的坑
    Java提供的几种线程池
    冒泡排序及优化详解
    如何让MySQL语句执行加速?
    关于https的五大误区
    127.0.0.1和0.0.0.0地址的区别
    宽带网络技术-大题重点
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13303148.html
Copyright © 2011-2022 走看看