zoukankan      html  css  js  c++  java
  • NOIP 模拟 $14; ext{队长快跑}$

    题解 (by;zjvarphi)

    一道很妙的 (dp) 题,方程状态不好设置,细节也不少

    看到数据范围,直接想离散化

    (f_{i,j}) 表示处理完前 (i) 个水晶,其中摧毁的 (A_i) 的最小值为 (j) 时最多能摧毁多少。

    分类讨论

    1. (A_ile B_i) 时,那么要使 (A_i) 为最小值,那么就要摧毁它,所以 (dp_{i,A_i}=max(dp_{i-1,B_i+1},...dp_{i-1,max})+1)
      但前 (i-1) 个数也可能有 (A_i) 所以也可以不摧毁它,故 (dp_{i,A_i}=max(dp_{i,A_i},dp_{i-1,A_i}))

    2. (A_i>B_i) 时,要使 (A_i) 为最小值,则 (dp_{i,A_i}=max(dp_{i-1,A_i+1},...dp_{i-1,max})+1)
      (jin (B_i,A_i]) 时,(dp_{i,j}=dp_{i-1,j}+1)

    对于第二种情况,我们要把其中的 (dp_{i,A_i}) 取最大值,至于为什么可以在不确定前 (i) 个数是否有 (j) 时就转移 (j)

    是因为若没有 (j),(dp_{i,A_i}) 绝对不会劣于 (dp_{i,j}),所以 (dp_{i,j}) 的会被 (dp_{i,A_i}) 覆盖。

    数据范围太大,无法直接转移,考虑线段树优化,转移的式子可以直接当作 单点修改,区间最大值,区间加法。

    Code
    #include<bits/stdc++.h>
    #define ri register signed
    #define p(i) ++i
    using namespace std;
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
        template<typename T>inline void read(T &x) {
            ri f=1;x=0;register char ch=gc();
            while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
            while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
            x=f?x:-x;
        }
    }
    using IO::read;
    namespace nanfeng{
        #define cmax(x,y) ((x)>(y)?(x):(y))
        #define cmin(x,y) ((x)>(y)?(y):(x))
        #define FI FILE *IN
        #define FO FILE *OUT
        static const int N=1e5+7;
        int a[N],b[N],tmpab[N<<1],n,ans,cnt;
        struct Seg{
            #define ls(x) (x<<1)
            #define rs(x) (x<<1|1)
            #define up(x) T[x].nm=cmax(T[ls(x)].nm,T[rs(x)].nm)
            struct segmenttree{int lz,nm;}T[N<<3];
            inline void down(int x) {
                if (!T[x].lz) return;
                int l=ls(x),r=rs(x);
                T[l].nm+=T[x].lz,T[l].lz+=T[x].lz;
                T[r].nm+=T[x].lz,T[r].lz+=T[x].lz;
                T[x].lz=0;
            }
            void update(int x,int l,int r,int lt,int rt) {
                if (l<=lt&&rt<=r) {p(T[x].nm),p(T[x].lz);return;}
                int mid(lt+rt>>1);
                down(x);
                if (l<=mid) update(ls(x),l,r,lt,mid);
                if (r>mid) update(rs(x),l,r,mid+1,rt);
                up(x);
            }
            void updates(int x,int p,int k,int l,int r) {
                if (l==r) {T[x].nm=cmax(T[x].nm,k);return;}
                int mid(l+r>>1);
                down(x);
                if (p<=mid) updates(ls(x),p,k,l,mid);
                else updates(rs(x),p,k,mid+1,r);
                up(x);
            }
            int query(int x,int l,int r,int lt,int rt) {
                if (l<=lt&&rt<=r) return T[x].nm;
                int mid(lt+rt>>1),res(0);
                down(x);
                if (l<=mid) res=max(res,query(ls(x),l,r,lt,mid));
                if (r>mid) res=max(res,query(rs(x),l,r,mid+1,rt));
                return res;
            }
        }T;
        inline int main() {
            // FI=freopen("nanfeng.in","r",stdin);
            // FO=freopen("nanfeng.out","w",stdout);
            read(n);
            for (ri i(1);i<=n;p(i)) {
                read(a[i]),read(b[i]);
                tmpab[p(cnt)]=a[i],tmpab[p(cnt)]=b[i];
            }
            sort(tmpab+1,tmpab+cnt+1);
            ri kab=unique(tmpab+1,tmpab+cnt+1)-tmpab;
            for (ri i(1);i<=n;p(i)) {
                a[i]=lower_bound(tmpab+1,tmpab+kab,a[i])-tmpab;
                b[i]=lower_bound(tmpab+1,tmpab+kab,b[i])-tmpab;
            }
            kab-=1;
            for (ri i(1);i<=n;p(i)) {
                int tmp=0;
                if (a[i]<=b[i]) {
                    if (b[i]<kab) tmp=T.query(1,b[i]+1,kab,1,kab);
                    T.updates(1,a[i],tmp+1,1,kab);
    
                } else {
                    T.update(1,b[i]+1,a[i],1,kab);
                    if (a[i]<kab) tmp=T.query(1,a[i]+1,kab,1,kab);
                    T.updates(1,a[i],tmp+1,1,kab);
                }
            }
            printf("%d
    ",T.T[1].nm);
            return 0;
        } 
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    .net 加伪静态的方法
    前台调用后台事件的方法
    关于一个网站的源码问题
    div里面有ul li时 让高度自适应的方法
    用insert语句写入汉字变成问号的解决
    .net 4.0 ValidateRequest="false" 无效
    修复 VS2008 asp.net 设计视图 失效/工具选项[Html设计视图]出现"加载此属性页时出错" 方案
    绑定数据时,时间格式的转换
    IE下CSS属性float:right下移换行或不显示的问题原因及解决
    珍惜生命,远离培训 《如何选择好的培训机构》读后感 JavaEye技术网站
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15010240.html
Copyright © 2011-2022 走看看