zoukankan      html  css  js  c++  java
  • Monotonicity 2[POI2010]

    题目描述

    给出N个正整数a[1..N],再给出K个关系符号(>、<或=)s[1..k]。
    选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1]。
    求出L的最大值。

    输入

    第一行两个正整数,分别表示N和K (N, K <= 500,000)。
    第二行给出N个正整数,第i个正整数表示a[i] (a[i] <= 10^6)。
    第三行给出K个空格隔开关系符号(>、<或=),第i个表示s[i]。

    输出

    一个正整数,表示L的最大值。

    样例输入

    7 3
    2 4 3 1 3 5 3
    < > =

    样例输出

    6
    

    提示

    选出的子序列为2 4 3 3 5 3,相邻大小关系分别是< > = < >。

    【题解】

        喜闻乐见的数据结构优化dp。看完了题,在演草纸上写了一句“动规吧?”,然后就把这句话放一边了。觉得二分应该能行,就写了个二分。怎么check呢?写了个dfs。后来跟wzz说这个事,大佬非常不理解地说:还不如直接深搜呢,白白地加个log。瞬间觉得好有道理啊,果然上午不知道干了些什么。

       下午听讲题,自己连O(n^2)的转移方程都没写出来,简直了。正解思路很清奇,f[i]表示到i这一位最长的子序列长度,有了长度符号就定下来了。不等号按符号维护线段树,等号直接拿数组标记一下。线段树的下标是a[i]的权值,内容是f[i]的权值,这样区间查询满足不等号的最大值就非常快了。得出f[i]之后推出下一位的符号,更新相应的线段树或数组即可。

        线段树是个好东西。上次方伯伯的玉米田用到了树状数组优化dp,这一次算是第二道数据结构优化dp。虽然在理论上来讲树状数组比线段树好打多了,可我始终还是更喜欢线段树。连续两天的dp题都是想过它是dp,但还是没按dp来做。学完一段时间以后dp能力下降得多了,想当初正在讲的时候也是不怕想正解的。原来以为自己不擅长数学和数据结构,现在看来dp也不是很行,集训要做的事还太多了啊。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int sj=500010;
    char fh[sj];
    int  n,k,a[sj],f[sj],dh[1000010],temp,jg,jd;
    void bj(int &x,int y)
    {
        x=x>y?x:y;
    }
    struct Tree
    {
        int l,r,jz; 
    }ds[1000010*4],xs[1000010*4];
    void bt1(int x,int y,int z)
    {
         ds[x].l=y;
         ds[x].r=z;
         if(y==z)  return;
         int mid=(y+z)>>1;
         bt1(x<<1,y,mid);
         bt1((x<<1)|1,mid+1,z);
    }
    void bt2(int x,int y,int z)
    {
         xs[x].l=y;
         xs[x].r=z;
         if(y==z)  return;
         int mid=(y+z)>>1;
         bt2(x<<1,y,mid);
         bt2((x<<1)|1,mid+1,z);
    }
    int query1(int x,int y,int z)
    {
        if(ds[x].l==y&&ds[x].r==z) return ds[x].jz;
        int mid=(ds[x].l+ds[x].r)>>1;
        if(mid<y) return query1((x<<1)|1,y,z);
        if(z<=mid) return query1(x<<1,y,z);
        return max(query1(x<<1,y,mid),query1((x<<1)|1,mid+1,z));
    }
    int query2(int x,int y,int z)
    {
        if(xs[x].l==y&&xs[x].r==z) return xs[x].jz;
        int mid=(xs[x].l+xs[x].r)>>1;
        if(mid<y) return query2((x<<1)|1,y,z);
        if(z<=mid) return query2(x<<1,y,z);
        return max(query2(x<<1,y,mid),query2((x<<1)|1,mid+1,z));
    }
    void update1(int x,int y,int z)
    {
        if(ds[x].l==ds[x].r&&ds[x].r==z)
        {
              ds[x].jz=y;
              return;
        }
        int mid=(ds[x].l+ds[x].r)>>1;
        if(mid<z)  update1((x<<1)|1,y,z);
        if(z<=mid) update1(x<<1,y,z);
        ds[x].jz=max(ds[x<<1].jz,ds[(x<<1)|1].jz);
    }
    void update2(int x,int y,int z)
    {
        if(xs[x].l==xs[x].r&&xs[x].r==z)
        {
              xs[x].jz=y;
              return;
        }
        int mid=(xs[x].l+xs[x].r)>>1;
        if(mid<z)  update2((x<<1)|1,y,z);
        if(z<=mid) update2(x<<1,y,z);
        xs[x].jz=max(xs[x<<1].jz,xs[(x<<1)|1].jz);
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        { 
          scanf("%d",&a[i]);
          bj(jd,a[i]);
        }
        for(int i=1;i<=k;i++) cin>>fh[i];
        bt1(1,1,jd);
        bt2(1,1,jd);
        for(int i=1;i<=n;i++)
        {
            if(dh[a[i]]+1>f[i]) f[i]=dh[a[i]]+1;
            if(a[i]!=jd)
            {
              temp=query1(1,a[i]+1,jd);
              if(temp+1>f[i]) f[i]=temp+1;
            }
            if(a[i]!=1)
            {
              temp=query2(1,1,a[i]-1);
              if(temp+1>f[i]) f[i]=temp+1;
            }
            temp=f[i]%k;
            if(!temp) temp=k;
            if(fh[temp]=='=') dh[a[i]]=f[i];
            if(fh[temp]=='>') update1(1,f[i],a[i]);
            if(fh[temp]=='<') update2(1,f[i],a[i]);
            bj(jg,f[i]);
        }
        printf("%d",jg);
        return 0;
    }
  • 相关阅读:
    使用 typeScript 规范代码
    图片 剪切 上传
    hybrid
    resful
    区块链
    前端数据采集 埋点 追踪用户系列行为
    kafka生产消息的速度跟什么有关?
    引用:实际数据库需求变化及演变
    HBase学习
    使用scala开发spark入门总结
  • 原文地址:https://www.cnblogs.com/moyiii-/p/7252464.html
Copyright © 2011-2022 走看看