dp[i][j]表示一个人吃了第i个另一个人吃了第j个时最多可以吃多少个苹果.
dp[i][j]=max(max(dp[i][k]),max(dp[k][j]))+1
可以用树状数组快速的求出dp[i]的某一段的最大值
1 5 1 1 2 3 3 2 4 3 5 1
4
/* *********************************************** Author :CKboss Created Time :2015年08月22日 星期六 08时49分41秒 File Name :HDOJ5406.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <cmath> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> using namespace std; const int maxn=2000; int n; int arr[maxn],an; struct Apple { int h,d; void toString() { printf("h: %d,d: %d\n",h,d); } }apple[maxn]; bool cmp(Apple x,Apple y) { if(x.h!=y.h) return x.h>y.h; return x.d<y.d; } /*********************BIT*****************************/ int t[maxn]; int tree[maxn][maxn]; inline int lowbit(int x) { return x&(-x); } void Update(int id,int p,int v) { for(int i=p;i<maxn;i+=lowbit(i)) { tree[id][i]=max(tree[id][i],v); } } int getMax(int id,int p) { int ret=0; for(int i=p;i;i-=lowbit(i)) { ret=max(ret,tree[id][i]); } return ret; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T_T; scanf("%d",&T_T); while(T_T--) { scanf("%d",&n); an=0; for(int i=1;i<=n;i++) { scanf("%d%d",&apple[i].h,&apple[i].d); arr[an++]=apple[i].d; } sort(arr,arr+an); an=unique(arr,arr+an)-arr; for(int i=1;i<=n;i++) apple[i].d=lower_bound(arr,arr+an,apple[i].d)-arr+1; sort(apple+1,apple+n+1,cmp); //for(int i=1;i<=n;i++) apple[i].toString(); memset(tree,0,sizeof(tree)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) t[j]=getMax(j,apple[i].d)+1; for(int j=1;j<=n;j++) { Update(j,apple[i].d,t[j]); Update(apple[i].d,j,t[j]); } } int ans=0; for(int i=1;i<=n;i++) ans=max(ans,getMax(i,an)); printf("%d\n",ans); } return 0; }