#1826 选择客栈
为什么我会写这道题题解?令人窒息。
其实这道题也可以用数据结构。
题面
丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号。每家客栈都按照某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示),且每家客栈都设有一家咖啡店,每家咖啡店均有各自的最低消费。
两位游客一起去丽江旅游,他们喜欢相同的色调,又想尝试两个不同的客栈,因此决定分别住在色调相同的两家客栈中。晚上,他们打算选择一家咖啡店喝咖啡,要求咖啡店位于两人住的两家客栈之间(包括他们住的客栈),且咖啡店的最低消费不超过 p 。
他们想知道总共有多少种选择住宿的方案,保证晚上可以找到一家最低消费不超过 p元的咖啡店小聚。
输入
第一行三个整数n ,k ,p,每两个整数之间用一个空格隔开,分别表示客栈的个数,色调的数目和能接受的最低消费的最高值;
接下来的n 行,第 i+1 行两个整数,之间用一个空格隔开,分别表示 i 号客栈的装饰色调和i 号客栈的咖啡店的最低消费
输出
输出只有一行,一个整数,表示可选的住宿方案的总数。
样例输入
5 2 3
0 5
1 3
0 2
1 4
1 5
样例输出
3
SOL
这种题可以用各种方法做,我的这种方法比较慢……蒟蒻就是这样(唉我Tcl)。
用
表示前i个客栈的cafe有几个小于等于
(有点像DP),vector数组
用来存
色调的每个旅馆的各个编号,然后乱搞。
对于每种色调的旅馆,都有一个数量
(即vector数组的size),对于第
种色调,如果色调为i的旅馆两两组合都合法,
就加上
,接下来只要能处理出不合法的情况就可以了,于是用到之前预处理好的
数组。
对于
当中相邻的俩旅馆
——如果她们之间没有小于等于
的cafe,那么她们的组合便不合法,如果这样递推下去有连续
组都不合法,我们统计的答案中就减去
。
看到这里您可能比较懵13。我画个图给您解释一下。
(1表示这种组合合法,0表示不合法)
如果把相邻的点连一条0或者1的边,那么就要找出所有连续的一段0边,并将其方案数减去
代码:
#include<bits/stdc++.h>
#define N 200200
using namespace std;
#define int long long
int a[N],n,k,p;
int f[N],ans;
vector<int>c[55];
signed main(){
scanf("%lld%lld%lld",&n,&k,&p);
for(int register i=1;i<=n;i++){
int col;
scanf("%lld%lld",&col,&a[i]);
if(p>=a[i])f[i]=f[i-1]+1;
else f[i]=f[i-1];
c[col].push_back(i);
}
for(int register i=0;i<k;i++){
int tot=c[i].size();
if(tot<=1)continue;
ans+=tot*(tot-1)>>1;
int num=0;
for(int register j=1;j<tot;j++){
int len=f[c[i][j]]-f[c[i][j-1]-1];
if(!len)num+=1ll;
if(len){ans-=(num)*(num+1)>>1;num=0;}
}
ans-=(num)*(num+1)>>1;//特殊处理最后一次
}
printf("%lld",ans);
return 0;
}