zoukankan      html  css  js  c++  java
  • 队爷的Au Plan CH Round #59

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan

    题解:看了题之后觉得肯定是DP+优化,因为昨天刚水了一道线段树优化DP的题,所以又想到线段树上去了。。。

            具体做法:

            我维护了一个单调递增的f,显然若i<j并且f[i]>f[j],那么f[j]就可以不用

            然后我们要找寻>=a[i]的就是连续的一段了,就可以用线段树来查询f[j]-s[j]的最大值了

            然后 n*logn 水过,居然拿下了first blood

    代码:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<iostream>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 #include<queue>
    11 #include<string>
    12 #define inf 1000000000
    13 #define maxn 250000
    14 #define maxm 500+100
    15 #define eps 1e-10
    16 #define ll long long
    17 #define pa pair<int,int>
    18 #define for0(i,n) for(int i=0;i<=(n);i++)
    19 #define for1(i,n) for(int i=1;i<=(n);i++)
    20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
    21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
    22 #define mod 1000000007
    23 using namespace std;
    24 inline int read()
    25 {
    26     int x=0,f=1;char ch=getchar();
    27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    28     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    29     return x*f;
    30 }
    31 int n,m,tot,a[maxn],b[maxn],f[maxn];
    32 struct seg{int l,r,mx;}t[4*maxn];
    33 void build(int k,int l,int r)
    34 {
    35     t[k].l=l;t[k].r=r;int mid=(l+r)>>1;t[k].mx=-inf;
    36     if(l==r)return;
    37     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    38 }
    39 void change(int k,int x,int y)
    40 {
    41     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
    42     if(l==r){t[k].mx=max(t[k].mx,y);return;}
    43     if(x<=mid)change(k<<1,x,y);else change(k<<1|1,x,y);
    44     t[k].mx=max(t[k<<1].mx,t[k<<1|1].mx);
    45 }
    46 int query(int k,int x,int y)
    47 {
    48     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
    49     if(l==x&&r==y)return t[k].mx;
    50     if(y<=mid)return query(k<<1,x,y);
    51     else if(x>mid)return query(k<<1|1,x,y);
    52     else return max(query(k<<1,x,mid),query(k<<1|1,mid+1,y));
    53 }
    54 int main()
    55 {
    56     freopen("input.txt","r",stdin);
    57     freopen("output.txt","w",stdout);
    58     n=read();m=read();
    59     for1(i,n)a[i]=read();
    60     for1(i,n)b[i]=b[i-1]+read();
    61     build(1,0,n);
    62     f[tot=0]=m;change(1,0,m);
    63     //for1(i,4*n)cout<<i<<' '<<t[i].l<<' '<<t[i].r<<' '<<t[i].mx<<endl;
    64     for1(i,n)
    65     {
    66       int x=lower_bound(f,f+tot+1,a[i])-f,y;
    67       if(f[x]<a[i])continue;else y=query(1,x,tot);
    68       //for0(j,tot)cout<<j<<' '<<f[j]<<endl;
    69       //cout<<i<<' '<<x<<' '<<y<<endl;
    70       if(i==n){printf("%d
    ",y+b[i]-a[i]);return 0;}
    71       if(y+b[i]-a[i]>f[tot])
    72        {
    73            //cout<<tot<<' '<<f[tot]<<endl;
    74         f[++tot]=y+b[i]-a[i];
    75         change(1,tot,f[tot]-b[i]);
    76        }
    77     }
    78     return 0;
    79 }
    View Code

           赛后发现别人的代码都很短,瞬间惊呆

           出题人说: 

           对于i状态,考虑j,k两个决策,j<k<i且f[j]>hard[i]&&f[k]>hard[i]。

           若j,k不为前面同一个决策转移得到,则k的决策层数显然会更大,即额外消耗更多,所以j优于k;

           若j,k为前面同一个决策l转移得到:

           f[j]=f[l]-sum[l]+sum[j]-hard[j]

           f[k]=f[l]-sum[l]+sum[k]-hard[k]

           f[j]-f[k]=sum[j]-sum[k]+hard[k]-hard[j]

           f[j]-sum[j]-(f[k]-sum[k])=hard[k]-hard[j]

        即f[j]-sum[j]> f[k]-sum[k],

          所以j决策优于k决策, 所以对于每一个状态i,最小的能够转移到i的决策总是最优的,这样只需要用单调队列维护决策即可(其实一个指针就OK了),时间复杂度为O(n)。

    代码:

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<iostream>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 #include<queue>
    11 #include<string>
    12 #define inf 1000000000
    13 #define maxn 250000
    14 #define maxm 500+100
    15 #define eps 1e-10
    16 #define ll long long
    17 #define pa pair<int,int>
    18 #define for0(i,n) for(int i=0;i<=(n);i++)
    19 #define for1(i,n) for(int i=1;i<=(n);i++)
    20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
    21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
    22 #define mod 1000000007
    23 using namespace std;
    24 inline int read()
    25 {
    26     int x=0,f=1;char ch=getchar();
    27     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    28     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
    29     return x*f;
    30 }
    31 int n,m,tot,a[maxn],b[maxn],f[maxn];
    32 int main()
    33 {
    34     freopen("input.txt","r",stdin);
    35     freopen("output.txt","w",stdout);
    36     n=read();f[0]=read();
    37     for1(i,n)a[i]=read();
    38     for1(i,n)b[i]=b[i-1]+read();
    39     int j=0;
    40     for1(i,n)
    41      {
    42      while(f[j]<a[i])j++;
    43      f[i]=f[j]+b[i]-b[j]-a[i];
    44      }
    45     printf("%d
    ",f[n]);
    46     return 0;
    47 }
    View Code

    出题人没卡线段树真是太良心了。好评!

  • 相关阅读:
    第三天 moyax
    mkfs.ext3 option
    write file to stroage trigger kernel warning
    download fomat install rootfs script
    custom usb-seriel udev relus for compatible usb-seriel devices using kermit
    Wifi Troughput Test using iperf
    learning uboot switch to standby system using button
    learning uboot support web http function in qca4531 cpu
    learngin uboot design parameter recovery mechanism
    learning uboot auto switch to stanbdy system in qca4531 cpu
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4069108.html
Copyright © 2011-2022 走看看