zoukankan      html  css  js  c++  java
  • bzoj1109:[POI2007]堆积木Klo

    传送门

    自己想的方向一直是对的,但是一直没有完全正确
    我一直没发现可以缩掉一维
    原本列出的dp方程是这样的
    (f[i]=f[j]+1(j<i&&a[j]<a[i]&&j-a[j]<=i-a[i]))(f[i])代表(i)移动到正确位置,前(i)个最多有多少个到正确位置)
    看着就是lis,实际上想也可以想得到lis是最优的
    然后你会发现满足后两个要求就满足了第一个要求,那么我们就可以按照(i-a[i])排序,然后做lis就行了
    PS.不可能移动到原位的显然不用考虑,判掉就行了
    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    void read(int &x) {
    	char ch; bool ok;
    	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    #define rg register
    #define lowbit(i) (i&(-i))
    const int maxn=1e6+10;
    int n,f[maxn],ans,mx,now;struct oo{int x,id;}a[maxn];
    void add(int x,int y){for(rg int i=x;i<=mx;i+=lowbit(i))f[i]=max(f[i],y);}
    int get(int x){int ans=0;for(rg int i=x;i;i-=lowbit(i))ans=max(ans,f[i]);return ans;}
    bool cmp(oo x,oo y){return x.id==y.id?x.x<y.x:x.id<y.id;}
    int main()
    {
    	read(n);
    	for(rg int i=1;i<=n;i++)read(a[i].x),a[i].id=i-a[i].x,mx=max(mx,a[i].x);
    	sort(a+1,a+n+1,cmp);
    	for(rg int i=1;i<=n;i++)if(a[i].id>=0)now=get(a[i].x-1)+1,ans=max(ans,now),add(a[i].x,now);
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    P4357 [CQOI2016]K远点对(KDTree)
    P4475 巧克力王国(KDTree)
    P4148 简单题(KDTree)
    P2479 [SDOI2010]捉迷藏
    P4169 [Violet]天使玩偶/SJY摆棋子
    P4455 [CQOI2018]社交网络
    P4575 [CQOI2013]图的逆变换
    P3755 [CQOI2017]老C的任务
    P5057 [CQOI2006]简单题
    批量修改文件名
  • 原文地址:https://www.cnblogs.com/lcxer/p/10409321.html
Copyright © 2011-2022 走看看