[BZOJ]1109: [POI2007]堆积木Klo
题解: 我们考虑第j个位置从第i个位置的转移
$$ i< j $$
$$ a[i]< a[j] $$
$$ i-a[i]\leqslant j-a[j] $$
看上去是个三维偏序 然后实质上满足2,3式 1式恒成立 然后就是二维偏序问题 我们考虑 直接对a数组排序 然后线段树做转移(当然树状数组也是可以的
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=3e5+10; const double eps=1e-8; #define ll long long using namespace std; struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int dp[MAXN],maxx[MAXN<<2]; int a[MAXN]; vector<int>vec; void update(int rt,int l,int r,int t,int k){ maxx[rt]=max(maxx[rt],k); if(l==r)return ; int mid=(l+r)>>1; if(t<=mid)update(rt<<1,l,mid,t,k); else update(rt<<1|1,mid+1,r,t,k); } int ans; void query(int rt,int l,int r,int ql,int qr){ if(ql>qr)return ; if(ql<=l&&r<=qr){ans=max(ans,maxx[rt]);return ;} int mid=(l+r)>>1; if(ql<=mid)query(rt<<1,l,mid,ql,qr); if(qr>mid)query(rt<<1|1,mid+1,r,ql,qr); } vector<int>v[1000006]; int main(){ int n=read(); int T=0; inc(i,1,n)a[i]=read(),v[a[i]].pb(i),T=max(T,a[i]),vec.pb(i-a[i]); sort(vec.begin(),vec.end()); int base=unique(vec.begin(),vec.end())-vec.begin(); int Maxx=0; for(int i=1;i<=T;i++){ if(v[i].size()==0)continue; for(int j=0;j<v[i].size();j++){ if(v[i][j]-i<0){dp[v[i][j]]=0;continue;} int t=lower_bound(vec.begin(),vec.begin()+base,v[i][j]-i)-vec.begin()+1; ans=0;query(1,1,base,1,t); dp[v[i][j]]=max(1,ans+1); Maxx=max(Maxx,dp[v[i][j]]); } for(int j=0;j<v[i].size();j++){ if(v[i][j]-i<0){continue;} int t=lower_bound(vec.begin(),vec.begin()+base,v[i][j]-i)-vec.begin()+1; update(1,1,base,t,dp[v[i][j]]); } } printf("%d\n",Maxx); return 0; }
1109: [POI2007]堆积木Klo
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1346 Solved: 506
[Submit][Status][Discuss]
Description
Mary在她的生日礼物中有一些积木。那些积木都是相同大小的立方体。每个积木上面都有一个数。Mary用他的
所有积木垒了一个高塔。妈妈告诉Mary游戏的目的是建一个塔,使得最多的积木在正确的位置。一个上面写有数i
的积木的正确位置是这个塔从下往上数第i个位置。Mary决定从现有的高塔中移走一些,使得有最多的积木在正确
的位置。请你告诉Mary她应该移走哪些积木。
Input
第一行为一个数n,表示高塔的初始高度。第二行包含n个数a1,a2,...,an,表示从下到上每个积木上面的数。
(1<=n<=100000,1<=ai<=1000000)。
Output
注意:请输出最多有多少点可以处在正确位置
Sample Input
5
1 1 2 5 4
1 1 2 5 4
Sample Output
3