[Codeforces Round #122 (Div. 1)] -D Two segments

版权声明:欢迎转载蒟蒻博客,但请注明出处: https://blog.csdn.net/LPA20020220/article/details/82929957

洛谷传送门

Codeforces传送门

题目描述

Nick has some permutation consisting of p p integers from 1 1 to n n . A segment [ l , r ] [l,r] ( l r l\le r ) is a set of elements p i p_{i} satisfying l i r l\le i\le r .

Nick calls a pair of segments [ a 0 , a 1 ] [a_{0},a_{1}] and [ b 0 , b 1 ] [b_{0},b_{1}] ( 1 a 0 a 1 ; b 0 b 1 n 1\le a_{0}\le a_{1};b_{0}\le b_{1}\le n ) good if all their ( a 1 a 0 + b 1 b 0 + 2 a_{1}-a_{0}+b_{1}-b_{0}+2 ) elements, when sorted in ascending order, form an arithmetic progression with a difference of 1 1 . That is, when they sorted in ascending order, the elements are in the form x , x + 1 , x + 2 , . . . , x + m 1 {x,x+1,x+2,...,x+m-1} , for some x x and m m .

Your task is to find the number of distinct pairs of good segments in the given permutation. Two pairs of segments are considered distinct if the sets of elements contained in these pairs of segments are distinct. For example, any segment [ l , r ] [l,r] $ (l<r) $can be represented as a pair of segments, as [ l , i ] [l,i] and [ i + 1 , r ] [i+1,r] ( l i r l\le i\le r ). As all these pairs consist of the same set of elements, they are considered identical.

See the notes accompanying the sample tests for clarification.

输入输出格式

输入格式:

The first line contains integer n n ( 1 n 3 1 0 5 1\le n\le 3·10^{5} ) — the permutation size. The second line contains n n space-separated distinct integers p i p_{i} , ( 1 p i n 1\le p_{i}\le n ).

输出格式:

Print a single integer — the number of good pairs of segments of permutation p p .

Please, do not use the %lld specifier to read or write 64 b i t 64-bit integers in С++. It is preferred to use the c i n cin , c o u t cout streams or the %I64d specifier.

输入输出样例

输入样例#1:

3
1 2 3

输出样例#1:

3

输入样例#2:

5
1 4 5 3 2

输出样例#2:

10

输入样例#3:

5
5 4 3 1 2

输出样例#3:

10

题目大意

给你一个 1 n 1\sim n 的排列, 求出有多少种方案选出两个区间 [ l 1 , r 1 ] [l_1, r_1] [ l 2 , r 2 ] [l_2,r_2] 满足其中所有元素排序后为一个公差为一的等差数列, 两种方案不同当且仅当两个区间合并后中元素不同。

解题分析

奇妙的思路。

只考虑原序列显然行不通, 我们肯定会将元素从小到大或从大到小逐次插入, 但我们怎么维护?

我们发现每次插入一个元素, 对区间个数形成影响的只有其两端的两个元素。

那么我们从大到小维护 F i ( x ) ( x [ i , n ] ) F_i(x)(x\in [i,n]) [ i , x ] [i,x] 的区间个数, 设 m n , m x mn,mx 分别表示原序列中 i i 两旁的两个元素。

  • m x &lt; i mx&lt;i 的时候, 显然新加入一个元素所有 [ i , x ] [i,x] 的区间个数会比 [ i + 1 , x ] [i+1,x] 1 1 F i ( x ) = F i + 1 ( x ) + 1 F_i(x)=F_{i+1}(x)+1
  • m n &lt; i &lt; m x mn&lt;i&lt;mx 的时候, 如果 x &gt; m x x&gt;mx 显然就不会增加区间个数, 所以 F i ( x ) = F i + 1 ( x ) + 1 ( x [ i , m x 1 ] ) F_i(x)=F_{i+1}(x)+1(x\in[i,mx-1]) F i ( x ) = F i + 1 ( x ) ( x [ m x , n ] ) F_i(x)=F_{i+1}(x)(x\in [mx,n])
  • i &lt; m n i &lt;mn 的时候, 如果 x &lt; m n x&lt;mn 那么仍然区间个数会 + 1 +1 , 当 m n &lt; x &lt; m x mn&lt;x&lt;mx 的时候等于贴在了一端, 所以个数不变, x &gt; m x x&gt;mx 的时候相当于结合了两个区间, 区间个数 1 -1 , 所以 F i ( x ) = F i + 1 ( x ) + 1 ( x [ i , m n 1 ] ) F_i(x)=F_{i+1}(x)+1(x\in[i,mn-1]) F i ( x ) = F i + 1 ( x ) ( x [ m n , m x 1 ] ) F_i(x)=F_{i+1}(x)(x\in[mn,mx-1]) F i ( x ) = F i + 1 ( x ) 1 ( x [ m x , n ] ) F_i(x)=F_{i+1}(x)-1(x\in[mx,n])

实质上我们只需要线段树区间 + + 再查询权值 2 \le2 的点的个数, 这个我们维护一个最小值, 最小值的个数, 最小值 + 1 +1 的个数即可。

代码如下:

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define ll long long
#define MX 300050
#define gc getchar()
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
int dat[MX], ind[MX];
struct Node {int mn, mcnt, m1cnt, tag;} tree[MX << 2];
int dot;
ll ans;
namespace SGT
{
	#define ls (now << 1)
	#define rs (now << 1 | 1)
	IN void pushup(R int now)
	{
		tree[now].mcnt = tree[now].m1cnt = 0;
		tree[now].mn = min(tree[ls].mn, tree[rs].mn);
		if(tree[ls].mn == tree[now].mn) tree[now].mcnt += tree[ls].mcnt, tree[now].m1cnt += tree[ls].m1cnt;
		if(tree[ls].mn == tree[now].mn + 1) tree[now].m1cnt += tree[ls].mcnt;
		if(tree[rs].mn == tree[now].mn) tree[now].mcnt += tree[rs].mcnt, tree[now].m1cnt += tree[rs].m1cnt;
		if(tree[rs].mn == tree[now].mn + 1) tree[now].m1cnt += tree[rs].mcnt;
	}
	void build(R int now, R int lef, R int rig)
	{
		if(lef == rig) return tree[now].mcnt = 1, void();
		int mid = lef + rig >> 1;
		build(ls, lef, mid), build(rs, mid + 1, rig);
		pushup(now);
	}
	IN void pushdown(R int now)
	{
		if(tree[now].tag)
		{
			tree[ls].tag += tree[now].tag, tree[ls].mn += tree[now].tag;
			tree[rs].tag += tree[now].tag, tree[rs].mn += tree[now].tag;
			tree[now].tag = 0;
		}
	}
	IN void modify(R int now, R int lef, R int rig, R int lb, R int rb, R int del)
	{
		if(lb > rb) return;
		if(lef >= lb && rig <= rb)
		{
			tree[now].mn += del;
			tree[now].tag += del;
			return;
		}
		pushdown(now);
		int mid = lef + rig >> 1;
		if(lb <= mid) modify(ls, lef, mid, lb, rb, del);
		if(rb >  mid) modify(rs, mid + 1, rig, lb, rb, del);
		pushup(now);
	}
	IN int query(R int now, R int lef, R int rig, R int lb, R int rb)
	{
		if(lef >= lb && rig <= rb)
		{
			if(tree[now].mn == 1) return tree[now].m1cnt + tree[now].mcnt;
			if(tree[now].mn == 2) return tree[now].mcnt;
			return 0;
		}
		pushdown(now);
		int mid = lef + rig >> 1; int ret = 0;
		if(lb <= mid) ret += query(ls, lef, mid, lb, rb);
		if(rb  > mid) ret += query(rs, mid + 1, rig, lb, rb);
		return ret;
	}
}
int main(void)
{
	int mn, mx, pos;
	in(dot); SGT::build(1, 1, dot);
	for (R int i = 1; i <= dot; ++i) in(dat[i]), ind[dat[i]] = i;
	for (R int i = dot; i; --i)
	{
		mn = MX, mx = 0;
		pos = ind[i];
		if(pos > 1) mn = min(mn, dat[pos - 1]), mx = max(mx, dat[pos - 1]);
		if(pos < dot) mn = min(mn, dat[pos + 1]), mx = max(mx, dat[pos + 1]);
		if(mx < i) SGT::modify(1, 1, dot, i, dot, 1);
		else if(mn < i && i < mx) SGT::modify(1, 1, dot, i, mx - 1, 1);
		else
		{
			SGT::modify(1, 1, dot, i, mn - 1, 1);
			if(mn ^ mx)
			SGT::modify(1, 1, dot, mx, dot, -1);
		}
		ans += SGT::query(1, 1, dot, i, dot);
	}
	printf("%I64d", ans - dot);
}

猜你喜欢

转载自blog.csdn.net/LPA20020220/article/details/82929957