杭电2019多校第十场 HDU-6701 Make Rounddog Happy(单调栈+枚举)

news/2024/5/19 0:23:18 标签: 单调栈, 枚举, 玄学复杂度

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6701

题意:求区间内数各不相同并且max(al,al+1,…,ar)−(r−l+1)≤k的区间的个数。

思路:当时读题忽略了区间内数各不相同这个条件,想着不就是单调栈加简单的组合数学吗?后来,写完样例不对才发现。。。。然后就想求出某一个数为终点的最长不重复区间和一某个数为起点的最长不重复区间,再和单调栈的求出的范围取个较大、较小值不就找出该数的作用区间了吗?后来想明白了,以他为终点和以他为起点的区间合起来不一定数不重复啊!然后就卡在怎么快速求包含一个数的最长不重复区间。然后,就没有然后了。。。。看了别人的思路,直接预处理出以某一个数为终点的最长不重复区间的L和一某个数为起点的最长不重复区间的端点R,然后直接枚举单调栈求出最大值左右区间较小的那一块求。如果就这么看的觉得时间太多,但其实均摊为nlong(n),为啥咱也不知道。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e5+10;
const int maxm=3e5+10;
int l[N],r[N],L[N],R[N],sta[N],top,pos1,pos2;
int n,a[N],k,x;
int pre[N],suf[N];
ll ans,len;
void getL()
{
	for(int i=1;i<=n;i++) pre[i]=0;
	L[0]=0;
	for(int i=1;i<=n;i++)
	{
		L[i]=max(pre[a[i]]+1,L[i-1]);
		pre[a[i]]=i;
	}
}
void getR()
{
	for(int i=1;i<=n;i++) suf[i]=n+1;
	R[n+1]=n+1;
	for(int i=n;i>=1;i--)
	{
		R[i]=min(suf[a[i]]-1,R[i+1]);
		suf[a[i]]=i;	
	}  
}
void getl()
{	
	top=0;
	for(int i=1;i<=n;i++)
	{
		while(top&&a[sta[top]]<=a[i])
			top--;
		if(top) l[i]=sta[top]+1;
		else l[i]=1;
		sta[++top]=i;
	}		
}
void getr()
{	
	top=0;
	for(int i=n;i>=1;i--)
	{
		while(top&&a[sta[top]]<=a[i])
			top--;
		if(top) r[i]=sta[top]-1;
		else r[i]=n;
		sta[++top]=i;
	}		
}
int main(void) 
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&k);
		ans=0; 
		for(int i=1;i<=n;i++) 
			scanf("%d",&a[i]);
		getL();
		getR();
		getl();
		getr();
		for(int i=1;i<=n;i++)
		{
			x=a[i]-k;
			//取左右两边个数少的来枚举 
			if(i-l[i]<r[i]-i)
			{
				//枚举区间左端点 
				for(int j=l[i];j<=i;j++)
				{
					//第一个可选的右端点,区间内必须要有i 
					pos1=max(i,j+x-1);
					//最后一个可选的右端点 
					pos2=min(r[i],R[j]);
					if(pos2>=pos1) ans+=pos2-pos1+1;	
				}
			} 
			else
			{
				//枚举区间右端点 
				for(int j=i;j<=r[i];j++)
				{
					//最后一个可选的左端点  
					pos1=max(l[i],L[j]);
					//第一个可选的左端点,区间内必须要有i 
					pos2=min(i,j-x+1);
					if(pos2>=pos1) ans+=pos2-pos1+1;
				}
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
} 

 


http://www.niftyadmin.cn/n/1847029.html

相关文章

CCPC网络赛 HDU-6703 array(主席树+set+思维)(查询区间内第一个大于等于k的数模板)

链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid6703 题意&#xff1a;多组样例。给出1~n的全排列&#xff0c;m个操作&#xff0c;操作有两种&#xff0c;第一种将a[pos]1e7&#xff1b;第二种询问不是[1,r]区间内的并不小于k的数。强制在线查询。 思路&#x…

CCPC网络赛 HDU-6706 huntian oy(莫比乌斯反演+杜教筛+sum(i*phi(i))模板)

链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid6706 题意&#xff1a;求 官方题解&#xff1a; 杜教筛强推博客&#xff1a;https://www.cnblogs.com/peng-ym/p/9446555.html #include <bits/stdc.h> #include <tr1/unordered_map> #define ll lo…

POJ - 3347 Kadj Squares (思维)

链接&#xff1a;https://cn.vjudge.net/problem/POJ-3347 题意&#xff1a;给出n个正方形&#xff0c;把正方形按顺序放进第一象限中并且正方形的两底边与x轴成45度角。尽可能让正方形紧挨着放。问俯视时&#xff0c;最后哪几个正方形不会被完全遮挡。 思路&#xff1a;如果…

POJ - 3348 Cows (凸包+凸多边形面积)

链接&#xff1a;Cows - POJ 3348 - Virtual Judge 题意&#xff1a;给出n个点。求把这n个点围起来的凸多边形的面积&#xff0c;然后除以50。 思路&#xff1a;凸包裸题&#xff0c;凸包不严格的说就是把所有点围起来的凸多边形。怎么求呢&#xff1f;按最左下的点进行极角排…

HDU-1392 Surround the Trees(凸包+周长)

链接&#xff1a;Problem - 1392 题意&#xff1a;求凸包的周长。 思路&#xff1a;凸包裸题。 #include <cstdio> #include <iostream> #include <cmath> #include <algorithm> using namespace std; const int N 1e210; const double eps 1e-8;…

POJ - 2826 An Easy Problem?! (线段与线段相交求交点模板+分类讨论)

链接&#xff1a;https://cn.vjudge.net/problem/POJ-2826 题意&#xff1a;给你两个线段&#xff0c;问能接住多少从y轴正方向倒下来的水&#xff1f; 思路&#xff1a;线段与线段相交求交点。具体可以看kaungbin大神的题解。https://www.cnblogs.com/kuangbin/p/3192511.ht…

POJ - 1584 A Round Peg in a Ground Hole (是否为凸多边形+点是否在多边形内+圆是否在多边形内)

链接&#xff1a;https://cn.vjudge.net/problem/POJ-1584 题意&#xff1a;判断多边形是否为凸多边形以及圆是否在多边形内。 思路&#xff1a;模板。详情看注释。 #include <cstdio> #include <iostream> #include <cmath> #include <algorithm> …

POJ - 2187 Beauty Contest (求距离最远点对-凸包+旋转卡壳/枚举 (旋转卡壳学习))

链接&#xff1a;https://vjudge.net/problem/POJ-2187 题意&#xff1a;求求距离最远点对。 思路&#xff1a;肯定为凸包上的点&#xff0c;可枚举&#xff0c;也可根据凸包性质旋转卡壳求对踵点。 参考博客&#xff1a; https://www.cnblogs.com/xdruid/archive/2012/07/…