首页 > 其他分享 >牛客多校赛第9场D Error Permutaition

牛客多校赛第9场D Error Permutaition

时间:2023-08-17 09:44:37浏览次数:33  
标签:int Permutaition 合法 牛客 端点 区间 -- 校赛 移动

给定一个长度为n的排列,计算满足条件的子区间的个数。

对于子区间\([l , r]\)要求任意区间第k小,不在区间的第k个位置上。

\(n <= 5000\)

从每个值入手,设这个值为先,寻找对于x来讲是不合法的区间,也就是x在这个区间中是第k小,并且在区间的第k个位置上。

1. 如果固定区间左端点l,那么右端点r的应该是一段区间。

固定的左端点l,那么x在区间中的位置就可以确定了,假设是t。

向右移动右端点时,区间中小于x的数的数目就会逐渐增加,当增加到和t相等时对应的一段r就是对x来讲不合法的区间。

2. 而如果将左端点向左侧移动时,右端点对应的区间不会向左侧移动。

因为l左移,则x在区间中的位置是一定增加1的,也就是t变成了t+1。

但是比x小的数不一定增加1,(因为l-1上的数不一定是比x小的)。

所以r只有可能向右移动来补足比x小的数的数量。

3. 对于各个数字不合法的区间取并集,剩余的就是合法的区间

用\(Not[i][j]\)表示区间\([l ,r]\)是否合法。

因为l固定时,不合法的区间的r是连续的一段。所以可以利用差分的思想,给这一段整体标记。

#include<iostream>
using namespace std;
const int N = 5010;
int A[N] , Not[N][N];

void Solve()
{
	int n , Answer = 0;
	cin >> n;
	for(int i = 1 ; i <= n ; ++i)
		cin >> A[i];
	for(int i = 1 ; i <= n ; ++i)
	{
		int r1 = i , r2 = i , cnt = 0;
		for(int l = i ; l >= 1 ; --l)
		{
			if(A[l] <= A[i]) cnt++;
			while(r2 + 1 <= n && cnt < i - l + 1)
			{
				r2++; r1 = r2;
				if(A[r2] <= A[i]) cnt++;
			}
			if(cnt == i - l + 1)
			{
				while(r2 + 1 <= n && A[r2 + 1] > A[i]) r2++;
				Not[l][r1]++; Not[l][r2 + 1]--;
				// cout << l << ' ' << r1 << ' ' << r2 << '\n';
			}
		}
	}
	for(int i = 1 ; i <= n ; ++i)
	{
		for(int j = i ; j <= n ; ++j)
		{
			Not[i][j] = Not[i][j] + Not[i][j-1];
			if(Not[i][j] == 0) Answer++;
		}
	}
	cout << Answer << '\n';
	for(int i = 1 ; i <= n + 1 ; ++i)
		for(int j = i ; j <= n + 1 ; ++j)
			Not[i][j] = 0;
}

int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int T;
	cin >> T;
	while(T--) Solve();
	return 0;
}

标签:int,Permutaition,合法,牛客,端点,区间,--,校赛,移动
From: https://www.cnblogs.com/sybs5968QAQ/p/17636774.html

相关文章

  • 2023牛客暑期多校训练营8
    A.AliveFossils纯模拟没啥好说的map<string,int>mp;voidsolve(){intn;cin>>n;for(inti=1;i<=n;i++){intt;cin>>t;while(t--){strings;cin>>s;mp[s]++;}}......
  • 2023牛客暑期多校训练营7
    C.BeautifulSequence题意:有长为\(n\)的数组\(a\),通过操作\(a_i\oplusa_{i+1}\)得到\(b_i\),现在给出数组\(b\),求出字典序第\(k\)小的数组\(a\)Solution不难发现,如果确定了\(a_1\)的某一二进制位上的数,就可以确定整个数组\(a\)的这一位上的数,我们首先把所有的二进制位数都变......
  • 2023牛客暑期多校训练营9--I Non-Puzzle: Segment Pair
    思路:直接枚举区间左端点,用一个cnt数组表示当前端点l,r或者L,R存在1个还是2个或者0个。用一个sum变量记录有多少段区间覆盖了该端点,如果sum==n那么这个端点就有了贡献。更详细的看代码注释。#include<bits/stdc++.h>usingnamespacestd;#defineIOSios::sync_with_stdio(fa......
  • 2023牛客多校(9)
    D首先考虑枚举一个左端点然后我们就会发现,对于一个位置来说,会影响它的只有前缀和后缀比它小的数于是让每个数字不合法的都是一个区间可以预处理$[L,i]$这个范围内有几个比它小的数,设为$x$然后就能知道第一个让它不合法的位置($i-L-x$)个比它小的数的位置而让它重新合法......
  • 2023牛客多校第九场 D Non-Puzzle: Error Permutation
    题意给定一个长度为n的序列,计算有多少个子区间满足子区间第K小的数不在子区间第K位。 找出所有不满足条件的区间。枚举所有的ai和左端点al,找出满足ai是区间[l,r]中第r-l+1小的右端点r,则右端点r一定是一段区间。例如   342165         l i ......
  • 23牛客多校9 I Non-Puzzle: Segment Pair
    也许更好的阅读体验\(\mathcal{Description}\)给\(n\)对区间,要求每对区间恰好选一个使得选出来的\(n\)个区间有交集,问有多少方案数\(1\len,l_i,r_i\le5×10^5\)\(\mathcal{Solution}\)注意到区间的值域也是\(5×10^5\),考虑从值域入手,也就是枚举每个点看有多少种方案使最后......
  • 牛客周赛 Round 7
    牛客周赛Round7A-游游的you矩阵_牛客周赛Round7(nowcoder.com)把四种字符凑一起看看有没有\(y,o,u\)就行#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;signedmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intn,m......
  • 2023牛客暑期多校训练营7 CGILM
    比赛链接C题解知识点:位运算,贪心。我们用分段的思想考虑大小关系,若在同一段则大小不能确定,一开始为\([1,n]\)。我们按位从高到低考虑,某位如果\(b_i\)产生了\(1\),那么会这一位的第\(i\)个数产生大小的分段,得到\([1,i-1]<[i,n]\),之后这两段的大小关系就确定了,我们可以......
  • 暑假牛客多校第八场 2023-8-11(H、K)
    H.Insert1,Insert2,Insert3,...算法:栈做法:   我们分析题目发现每个区间的左端点一定是\(1\),而且每个新加入的数\(x\)一定是匹配最靠近它的且未经匹配的\(x-1\)。举个例子,在[1,1,2,2,3]中我们加入一个数\(3\)时由于从左到右的第二个\(2\)是已经和第一个......
  • 牛客sql-计算用户的平均次日留存率
    参考大佬题解做一下记录:https://blog.nowcoder.net/n/fe24f96a26f1437da19e91ab1d035b03?f=commenthttps://blog.nowcoder.net/n/dd3d75ce08e3485c95bafe3c23668fc2?f=comment https://www.runoob.com/sql/sql-dates.htmlDATE_ADD(date,intervalexprtype) date参数是合......