bzoj3594[Scoi2014]方伯伯的玉米田
http://www.lydsy.com/JudgeOnline/problem.php?id=3594
题目就是问你至多操作K次后的最长上升子序列。
首先,我们会得到一个结论:每次操作区间的右端点一定是n。
记$F[i][j]$表示前$i$棵玉米,使用$j$次操作时,以第$i$棵玉米为结尾的最长上升子序列的长度,则:
$$F[i][j]=Max\{F[k][l]|k<i,l\leq j,a[k]+l \leq a[i]+j\}+1$$
状态$F[i][j]$等价于一个三元组$(i,a[i]+j,j)$
其实就是求三元组的三维偏序。
然后我脑抽用CDQ分治,结果TLE。。。。。。~OTATO~
发现其实用二维树状数组即可。
真是*了狗了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define fill(a,l,r,v) fill(a+l,a+r+1,v) #define re(i,a,b) for(i=(a);i<=(b);i++) #define red(i,a,b) for(i=(a);i>=(b);i--) #define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define p_b(a) push_back(a) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxn=10000; const int maxK=500; const int maxv=5000+maxK; int n,K; int a[maxn+100],v; int f[maxn+100][maxK+10],ans; #define lowbit(a) ((a)&(-a)) int tr[maxv+100][maxK+100]; void update(int x,int y,int val) { int i,j; for(i=x;i<=v;i+=lowbit(i)) for(j=y+1;j<=K+1;j+=lowbit(j)) upmax(tr[i][j],val); } int ask(int x,int y) { int res=0,i,j; for(i=x;i>=1;i-=lowbit(i)) for(j=y+1;j>=1;j-=lowbit(j)) upmax(res,tr[i][j]); return res; } int main() { freopen("bzoj3594.in","r",stdin); freopen("bzoj3594.out","w",stdout); int i,j; n=gint();K=gint(); re(i,1,n)a[i]=gint(),upmax(v,a[i]); v+=K; re(i,1,n) { re(j,0,K)f[i][j]=ask(a[i]+j,j)+1; re(j,0,K)update(a[i]+j,j,f[i][j]); re(j,0,K)upmax(ans,f[i][j]); } cout<<ans<<endl; return 0; }