BZOJ1345:[Baltic2007]序列问题Sequence 乱搞
BZOJ1043:[HAOI2008]下落的圆盘 计算几何+离线处理

BZOJ3357:[Usaco2004]等差数列 dp

shinbokuow posted @ Jan 15, 2015 04:07:46 PM in BZOJ with tags DP , 1374 阅读

思路:

我们令\(f[i][j]\)表示等差数列最后两项的下标分别为\(i,j\)时的最长长度.

显然我们有:

\[f[i][j]=max_{k=1}^{i-1}\{f[k][i]+1\}(2a[i]=a[j]+a[k])\]

重要的就是如何快速找出\(k\)的位置.

我们呢就可以将权值离散化,记录一下每个权值在序列中出现的位置.

于是我们要找的\(k\),显然就是权值相同时标号小于\(i\)且最大的一个.

因此我们维护一个vector然后二分就好了.

(注意\(n=1\)233)

 

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;
 
#define N 2010
vector<int>v[N];
 
int a[N],b[N],id;
map<int,int>M;
 
int f[N][N];
 
int main(){
    int n;scanf("%d",&n);if(n==1){puts("1");return 0;}register int i,j;for(i=1;i<=n;++i)scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);for(b[0]=-1<<30,i=1;i<=n;++i)if(b[i]!=b[i-1])M[b[i]]=++id;
    for(i=1;i<=n;++i)v[M[a[i]]].push_back(i);
    int nowv,ins,siz;
    for(j=2;j<=n;++j){
        for(i=1;i<j;++i){
            f[i][j]=2;
            nowv=M[2*a[i]-a[j]];
            if(nowv){
                siz=v[nowv].size();
                if(v[nowv][0]<i){
                    int L=0,R=siz-1,mid;
                    while(L<R){
                        mid=(L+R+1)>>1;
                        if(v[nowv][mid]<i)L=mid;else R=mid-1;
                    }f[i][j]=max(f[i][j],f[v[nowv][L]][i]+1);
                }
            }
        }
    }
    int res=0;for(i=1;i<=n;++i)for(j=i+1;j<=n;++j)res=max(res,f[i][j]);
    printf("%d",res);
    return 0;
}
蒟蒻 说:
Mar 10, 2015 11:16:16 PM

(注意n=1/233)
黑色的什么心态

Avatar_small
wyfcyx 说:
Mar 13, 2015 08:32:58 AM

@蒟蒻: 如果有人被坑了看到这个就会有充满希望AC的感觉,这不是很好?


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter