把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P1311 选择客栈&&luogu P6032 选择客栈 加强版

题面传送门
题面传送门(加强版)
其实这两道题是双倍经验啦哈哈。
这道题要求所有\(x\)\(y\)满足\(x\neq y\&\&a_x=a_y\&\&min(b_k)<=p\&\&x\leq k\leq y\)
我们设\(a_i\)为第\(i\)种元素的当前最后一个的值,\(b_i\)表示第\(i\)中颜色到当前位置已经可以有\(min(b_k)<=p\)的数的个数,\(c_i\)表示第\(i\)种颜色当前总共有的个数。
维护一个前缀和数列\(q\),令\(q_i\)表示到\(i\)这个元素有几个\(\leq p\)的元素。
则来了一个客栈时,先维护好\(b_i\),如果这一段距离中有\(>p\)的元素,那么\(b_i=c_i\),特殊的,如果当前的\(y\leq p\),那么\(b_i=c_i+1\),然后答案加上\(b_i\),维护\(a_i\)\(c_i\)
代码实现:

#include<cstdio>
using namespace std;
int n,m,k,a[10039],b[10039],c[10039],q[2000039],tot,pus,now,x,y;
long long ans;
inline void read(int &x){
	char s=getchar();x=0;
	while(s<'0'||s>'9')s=getchar();
	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
int main(){
	register int i;
	scanf("%d%d%d",&n,&m,&k);
	for(i=1;i<=n;i++){
		read(x);read(y);
		if(y<=k) q[i]=1;
		q[i]+=q[i-1];
		if(!a[x])a[x]=i,b[x]=q[i]-q[i-1],c[x]=1;
		else{
			if(q[i-1]-q[a[x]])b[x]=c[x];
			if(q[i]-q[i-1]) b[x]=c[x]+1,ans--;
			c[x]++;
			ans+=b[x];
			a[x]=i;
		}
		//printf("%lld\n",ans);
	}
	printf("%lld\n",ans);
}

毒瘤神鱼为什么不把\(k\)加强到\(n\)一样大呢?

posted @ 2020-03-31 18:12  275307894a  阅读(42)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end