zoukankan      html  css  js  c++  java
  • [ZOJ]ZOJ4003(双指针)

    题意:给出两个序列An,Bn,有多少对等长的子序列Ai-j和Bi-j之间的距离小于等于v,两个子序列的距离定义为 ∑ (|ai-bi|^p) (p<=3)

    暴力的做法是n^3枚举两个区间起点和最大长度,考虑优化。

    以Ai和Bj为起点时,因为距离公式的每一项都非负,显然最大长度至少是以Ai-1和Bj-1为起点是的最大长度减一。因此每次暴力的时候记录下最大长度和这一段的距离,之后就可以再次使用。因为区间右端点是单调递增的,也就是长度最多扩大n次。类似于双指针,可以证明复杂度是O(n^2)的。

    之前选拔赛也做过一道类似的双指针题,这类题目就是利用单调性和之前的计算结果减少枚举次数,降低复杂度。本质上还是暴力。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    #define rep(i,n) for(int i=1;i<=n;i++)
    
    const int N=1005;
    LL a[N],b[N];
    
    int l[N][N];
    
    LL sum[N][N];
    
    LL n,v,p;
    
    inline LL f(int i,int j)
    {
        LL res=1,x=abs(a[i]-b[j]);
        rep(i,p)res*=x;
        return res;
    }
    int main()
    {
    
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%lld%lld%lld",&n,&v,&p);
            rep(i,n)scanf("%lld",&a[i]);
            rep(i,n) scanf("%lld",&b[i]);  
            LL ans=0;
            rep(i,n)
            {
                rep(j,n)
                {
                    LL now=sum[i-1][j-1]-f(i-1,j-1);
                    int k;
                    for(k=l[i-1][j-1]-1; i+k<=n&&j+k<=n; k++)
                    {
                        if(now+f(i+k,j+k)<=v)
                            now+=f(i+k,j+k);
                        else
                            break;
                    }
                    sum[i][j]=now;
                    l[i][j]=k;
                    ans+=k;
                }
            }
    
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    rsync+inotify-tools实时备份脚本
    rsync+inotify实现实时同步
    linux 上安装部署python
    rsync全网备份low方法
    rsync 参数说明及使用参数笔记好文摘抄
    rsync 参数说明及使用参数笔记
    js DOM
    导出Excel
    Linux(CentOS 8)安装docker
    Win10安装虚拟机
  • 原文地址:https://www.cnblogs.com/xutianshu/p/10591587.html
Copyright © 2011-2022 走看看