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

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

  • 相关阅读:
    Spring Security(十七):5.8 Method Security
    Spring Security(十六):5.7 Multiple HttpSecurity
    Spring Security(十五):5.6 Authentication
    Spring Security(十四):5.4 Authorize Requests
    Spring Security(十三):5.2 HttpSecurity
    Spring Security(十二):5. Java Configuration
    Spring Security(十一):4. Samples and Guides (Start Here)
    Spring Security(十):3. What’s New in Spring Security 4.2 (新功能)
    Spring Security(九):2.4.4 Checking out the Source(检查来源)
    Spring Security(八):2.4.3 Project Modules
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4069108.html
Copyright © 2011-2022 走看看