看起来noip特别喜欢考这种思维题==
题意:有n家客栈,每家客栈有一个颜色和一个花费。给定最大允许花费,选择两家颜色相同的客栈,问有多少种选择方式使得两家客栈之间至少有一家花费允许的最大值的客栈
可以想到一些 n² 甚至 n³ 的方法,但显然不足以满足所有数据
考虑对于每一家客栈,从右往左扫描,找到第一家满足条件的颜色相同的客栈,其左边的所有颜色相同的客栈也就都满足条件了
所以此题可以巧妙地运用一些临时变量来记录当前可行的方案数,从而O(n)地解决问题
详见代码
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxk=55; int tot_col[maxk],last[maxk],linshi[maxk]; //tot_col表示每个颜色出现的总次数,last表示该种颜色上一次出现的位置 int main(){ int n,k,p; int pos,ans=0; scanf("%d%d%d",&n,&k,&p); for (int i=1;i<=n;i++){ int color,cost; scanf("%d%d",&color,&cost); if (cost<=p) pos=i; //显然消费满足条件的客栈越往右越优,所以在整个过程中只要保留最右边的一家消费小于q的客栈位置即可 if (pos>=last[color]) linshi[color]=tot_col[color]; //linshi记录的是在当前条件下,左边一共有多少家该颜色的客栈满足条件,读入时一边更新即可 ans+=linshi[color]; last[color]=i; tot_col[color]++; } printf("%d ",ans); return 0; }