codeforces1175F The Number of Subpermutations

https://codeforces.com/problemset/problem/1175/F

艹,还能这么玩?

由于我们需要一段序列包含1-r-l+1,直接1-n随机一个ull数字b[i]

然后一段区间要是出现了子全排列,那么这段区间异或之和就是b[i]异或之和(加法之和应该也可以)

然后我们只要枚举每个1的两边,假设最大数字再右边(之后反着再来一遍),看一下r-mx+1这段区间是不是子全排列就行了

这题分治怎么做啊。。。不会啊。。。

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;

const int maxl=3e5+10;

int n;ull ans;
int a[maxl];
ull b[maxl],pre[maxl],c[maxl];
mt19937 rnd(time(NULL));

inline void prework()
{
	scanf("%d",&n);
	ans=0;
	for(int i=1;i<=n;i++)
	{	
		scanf("%d",&a[i]);if(a[i]==1)++ans;
		b[i]=rnd();
		pre[i]=pre[i-1]^b[i];
	}

}

inline void solv()
{
	int mx,len;
	for(int i=1;i<=n;i++)
	if(a[i]==1)
	{
		mx=1;len=1;
		for(int j=i-1;j>=0 && a[j]!=1;j--)
			len++;
		for(int j=i+1;j<=n && a[j]!=1;j++)
		{
			mx=max(a[j],mx);
			if(mx>=j-i+1 && mx<=len+j-i && (c[j]^c[j-mx])==pre[mx])
				++ans;
		}
	}
}

inline void mainwork()
{
	for(int i=1;i<=n;i++)
		c[i]=c[i-1]^b[a[i]];
	solv();
	reverse(a+1,a+1+n);
	for(int i=1;i<=n;i++)
		c[i]=c[i-1]^b[a[i]];
	solv();
}

inline void print()
{
	printf("%llu",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/109063436
今日推荐