题目链接:https://loj.ac/problem/2597
解题思路
本题用ST算法在LOJ上会爆内存,因为数据量最大2e6,据说换成char不会爆但我不会QAQ ,在洛谷上,最大数据量只有2e5,可以过。还有一种O(n)的方法,直接线性递推,不过比较难想,每次枚举第二个酒店,然后看前面小于等于p的酒店在哪,如果在上一个就更新sum,否则不更新。
ST版
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=2e6+5;
const int maxm=1e4+5;
const int LogN=21;
int f[maxn][LogN+5];
int log[maxn];
int n,k,p;
ll ans;
vector<int>col[maxm];
int gmin(int a,int b)
{
if(a>=b)
return b;
else
return a;
}
int main()
{
scanf("%d%d%d",&n,&k,&p);
int x,y;
log[0]=-1;
for(int i=1;i<=n;++i)
{
scanf("%d%d",&x,&y);
log[i]=log[i>>1]+1;
col[x].push_back(i);
f[i][0]=y;
}
for(int j=1;j<=LogN;++j)
for(int i=1;i<=n;++i)
f[i][j]=gmin(f[i][j-1],f[i+(1<<j-1)][j-1]);
for(int i=0;i<k;++i)
{
int len=col[i].size();
for(int j=0;j<len;++j)
for(int t=j+1;t<len;++t)
{
int l=col[i][j];
int r=col[i][t];
int s=log[r-l+1];
if(gmin(f[l][s],f[r-(1<<s)+1][s])<=p)
{
ans+=1ll*(t-j)*(len-t);
j=t-1;
//cout<<i<<" "<<j<<" "<<ans<<endl;
break;
}
}
}
printf("%lld\n",ans);
return 0;
}
线性版
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=2e6+5;
typedef long long ll;
//last这种颜色最后一次出现的位置
//sum当前颜色满足条件的数量
//cnt当前颜色的数量
int last[maxn],sum[maxn],cnt[maxn];
ll ans;//方案数
int now;//最后小于等于p的酒店位置
int col;//颜色
int price;//价格
int n,k,p;
int main()
{
scanf("%d%d%d",&n,&k,&p);
for(int i=1;i<=n;++i)
{
scanf("%d%d",&col,&price);
if(price<=p)
now=i;
if(now>=last[col])
sum[col]=cnt[col];
last[col]=i;
ans+=(ll)sum[col];
cnt[col]++;
}
printf("%lld\n",ans);
return 0;
}