標籤:
首先,預先處理三個數組。
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 1e9using 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吧,看來我見識的題還是太少了。。。
(我是不會告訴你這是抄的,不過上面的解釋部分我自己補充了一下)
code1135 選擇客棧