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\)一样大呢?