标签:
首先,预处理三个数组。
pre[x]表示在此之前颜色为x的客栈有多少个。
f[x]表示在此之前的客栈中,某个点c,c的颜色为x,并且从c点到已经读入的点之间有费用小于p的客栈,这样的c点的个数
last[x]表示上一个颜色为x的客栈出现在哪
那么接下来的事情就很显然了。
首先读进去一个客栈,如果这个客栈满足费用小于等于p,就把它存下来,为temp(也就是说找到一个最近的费用满足题目要求的客栈)
接下来,如果客栈temp在上一个此颜色的客栈之后出现,那么就更新f[x]为pre[x]。(因为temp是满足费用的,那么在此之前所有颜色为x点pre[x]都能满足我们之前对点c的定义,所以都加入f数组)
每次ans+=f[x]。当前新读入的点的颜色为x,那么它与前面所有颜色为x且满足费用的(即f[x])都可以匹配,所以加入ans
最后,更新你的pre和last数组即可
代码:
#include <set> #include <map> #include <cmath> #include <queue> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define write(a) printf("%d\n",a); #define REP(i,a,b) for (int i=(a);i<=(b);i++) #define PER(i,a,b) for (int i=(a);i>=(b);i--) #define N 200005 #define M 1000005 #define INF 1e9 using namespace std; template <class T> inline void read(T& num) { bool start=0,neg=0; char c; num=0; while ((c=getchar())!=EOF) { if (c==‘-‘) start=neg=1; else if (c>=‘0‘ && c<=‘9‘) { start=1; num=num*10+c-‘0‘; } else if (start) break; } if (neg) num=-num; } /*===========Head Template================*/ int n,m,p; int f[N],pre[N],last[N]; int ans=0; int main() { read(n);read(m);read(p); int x,y,tmp; REP(i,1,n) { read(x);read(y); if (y<=p) tmp=i; if (tmp>=last[x]) f[x]=pre[x]; ans+=f[x]; pre[x]++; last[x]=i; } write(ans); }
这应该也算dp吧,看来我见识的题还是太少了。。。
(我是不会告诉你这是抄的,不过上面的解释部分我自己补充了一下)
标签:
原文地址:http://www.cnblogs.com/FuTaimeng/p/5652377.html