1. 程式人生 > >[BZOJ]1109: [POI2007]堆積木Klo

[BZOJ]1109: [POI2007]堆積木Klo

tor light zoj long true while for data gin

題解: 我們考慮第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 MB
Submit: 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

Sample Output

3

[BZOJ]1109: [POI2007]堆積木Klo