1167E - Range Deleting 双指针

题意:给出n个数的序列,并给出x,这n个数的范围为[1,x],f(L,R)表示删除序列中取值为[l,r]的数,问有几对L,R使得操作后的序列为非递减序列
思路:若[l,r]成立,那么[l,r+1],.....,[l,x]都成立,且若[l,r]成立,那么[l+1,r]不成立,不存在[l+1,r-1]成立, 所以可以看出本题区间具有单调性,可以用双指针求解
说明:\(t_i\)表示i值的最右边坐标,\(s_i\)表示i值的最左边坐标
若f(l,r)成立要满足三个条件
1.\(max(t_1,t_2,...,t_l)<min(s_r,s_{r+1},....s_x)\)
2.\(max(t_1,t_2,...,t_{i-1})<s[i](1<=i<=l)\)
3.\(t_{i}<min(s_{i+1},s_{i+2},....s_x)(r<=i<=x)\)
这里可以用类似前缀和的思想把这几个条件预处理处理,然后直接套用双指针即可
Reference:
https://www.cnblogs.com/henry-1202/p/10888691.html (大佬博客)
https://baijiahao.baidu.com/s?id=1615129382322508344&wfr=spider&for=pc (洛谷双指针总结)
https://www.cnblogs.com/xyq0220/p/10875872.html

#include<bits/stdc++.h>
#define F first
#define S second
#define pii pair<int,int>
#define pb push_back
#define mkp make_pair
#define all(zzz) (zzz).being(),(zzz).end()
#define pii pair<long long ,int>
typedef long long ll;
typedef long long LL;
using namespace std;
const int maxn=1e6+7;
int s[maxn],t[maxn],ss[maxn],tt[maxn],a[maxn],precan[maxn],lastcan[maxn];
bool check(int l,int r){
	return precan[l-1]&&lastcan[r+1]&&ss[r+1]>tt[l-1];
}
int main(){
	int n,x;
	scanf("%d%d",&n,&x);
	memset(s,0x3f3f3f3f,sizeof(s));
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++){
		s[a[i]]=min(s[a[i]],i);
		t[a[i]]=max(t[a[i]],i);
	}
	
	long long  ans=0;
	for(int i=1;i<=x;i++){
		tt[i]=max(tt[i-1],t[i]);
	}
	ss[x+1]=0x3f3f3f3f;
	for(int i=x;i>=1;i--){
		ss[i]=min(ss[i+1],s[i]);
	}
	precan[0]=1;
	lastcan[x+1]=1;
	for(int i=1;i<=x;i++)precan[i]=precan[i-1]&&(tt[i-1]<s[i]);
	for(int i=x;i>=1;i--)lastcan[i]=lastcan[i+1]&&(ss[i+1]>t[i]);
	int r=1;
	for(int l=1;l<=x;l++){
		if(l>r)r++;
		while(r<x&&!check(l,r))r++;
		if(check(l,r))ans+=x-r+1;
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2019-07-18 05:17  tttttttttrx  阅读(186)  评论(0编辑  收藏  举报