LOJ 模拟赛

1.LOJ 507 接竹竿

link

dp[i]表示前i个的最大分数,所以dp[i]=max(dp[i-1],dp[j-1]+sum[i]-sum[j-1])   (color i ==color j&&i>j)选与不选的两种决策

但是这样跑为O(N^2),需要优化,发现dp[j-1]-sum[j-1]是个在之前知道的数,所以可以记录下来当需要用这种颜色时的最大dp[j-1]-sum[j-1]

用lst[i]表示在当前情况下需要用color i这种颜色时的最大dp[j-1]-sum[j-1]这个值,因为这两者之间的共处是颜色

所以用颜色维护

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline long long read()
{
    long long f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
long long n,k;
long long c[6000001],v[6000001],lst[6000001],sum[6000001],dp[6000001];
int main()
{
    memset(lst,-127/3,sizeof(lst));
    n=read(),k=read();
    for(long long i=1;i<=n;i++) c[i]=read();
    for(long long i=1;i<=n;i++) v[i]=read(),sum[i]=sum[i-1]+v[i];
    for(long long i=1;i<=n;i++)
    {
        dp[i]=max(dp[i-1],lst[c[i]]+sum[i]);
        lst[c[i]]=max(lst[c[i]],dp[i-1]-sum[i-1]);
    }
    cout<<dp[n];
}
View Code

2.LOJ 2279 降雨量

link

这道题先要仔细的读题,读完题后发现此题十分可做,但是最后全WA,因为没有看到它的含义是 X 年的降雨量不超过 Y  年这句话

分类讨论+ST表

先用ST表处理(i,j)之间的最大值(i,j为年份下标)

解决问题如果询问i,j

二分寻找u,v年份下标

用nx记录查找的下标对应的值是否等于此年份,因为有可能没有u,v年份的降雨量

然后分类讨论(this is 重点,not ST表)

1)nx==1时

        1)ny==1时 已知 x,y(降水量) 那么首先判断x,y的大小,在判断包含区间的关系

        2) ny==0时,说明只能与u进行比较,中间包含最大值与x的关系

2)nx==0

      1) ny==1时,找中间包含区域与y的关系

       2)  ny==0,那么两头全部位置,所以maybe

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
inline long long read()
{
    long long f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
long long ma[50001];
long long n,m;
long long maxn[50001][31];
long long query(long long l,long long r)
{
    if(l>r) return -(2<<30-1);
    long long k=log2(r-l+1);
    return max(maxn[l][k],maxn[r-(1<<k)+1][k]);
}
long long num;
int main()
{
//    freopen("rainfall.in","r",stdin);
//    freopen("rainfall.out","w",stdout);
//    freopen("1.in","r",stdin);
    n=read();
    for(long long i=1;i<=n;i++)
    {
        ma[i]=read();
        maxn[i][0]=read();
    }
    for(long long j=1;j<=log2(n);j++)
        for(long long i=1;i+(1<<j)-1<=n;i++) maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
    m=read();
    for(long long i=1;i<=m;i++)
    {
        int ans;
        long long x=read(),y=read();
        int sx=lower_bound(ma+1,ma+n+1,x)-ma,sy=lower_bound(ma+1,ma+n+1,y)-ma;
        bool nx=(sx<=n&&ma[sx]==x),ny=(sy<=n&&ma[sy]==y);
//        cout<<sx<<" "<<sy<<" "<<nx<<" "<<ny<<endl;
        if(nx)
        {
            if(ny)
            {
                int q=query(sx+1,sy-1);
//                cout<<q<<" "<<maxn[sx][0]<<" "<<maxn[sy][0]<<endl;
                if(maxn[sy][0]>maxn[sx][0]) ans=0;
                else if(q<maxn[sy][0])
                {
                    if(y-x+1==sy-sx+1) ans=1;
                    else ans=-1;
                }
                else ans=0;
            }
            else{
                int q=query(sx+1,sy-1);
                if(maxn[sx][0]>q) ans=-1;
                else ans=0;
            }
        }
        else{
            if(ny)
            {
                int q=query(sx,sy-1);
                if(q<maxn[sy][0]) ans=-1;
                else ans=0;
            }else ans=-1;
        }
        if(ans==1) printf("true\n");
        else if(ans==0) printf("false\n");
        else printf("maybe\n");
    }
}
/*
4
54 8606
77 7706
100 2149
123 900
1
2 54

*/
View Code

3.LOJ 2332 焚风现象

link

官方讲评

因为是可以升降海拔高度的但是算的是差值,所以[u,v]区域内答案没有发生影响,至于(u-1,u)与(v,v+1)有影响

每次算值现将二者减去,再分别减,加差值,因为+w所以dis[u-1]+w ,但是对于v来说它是减数所以当他加上一个值时反而是减所以dis[v]-=w

dis[i]表示从i到i+1的海拔高

而因为若v=n时v+1已经越界所以就不再计算

此方法时间复杂度O(q+n)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline long long read()
{
    long long f=1,ans=0;char c;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
long long n,q,a[500001],s,t,dis[500001];
long long get(long long tt)
{
    if(tt>0) return -s*tt;
    return -tt*t; 
}
long long ans;
int main()
{
    n=read(),q=read(),s=read(),t=read();
    for(long long i=0;i<=n;i++) a[i]=read();
    for(long long i=0;i<n;i++)
    {
        dis[i]=a[i+1]-a[i];
        ans+=get(dis[i]);
    }    
    while(q--)
    {
        long long a=read(),b=read(),c=read();
        ans-=get(dis[a-1]);
        dis[a-1]+=c;
        ans+=get(dis[a-1]);
        if(b!=n)
        {
            ans-=get(dis[b]);
            dis[b]-=c;
            ans+=get(dis[b]);
        }
        printf("%lld\n",ans);
//        cout<<ans<<endl;
    }
}
View Code

 

总结:这其实是一场考试,最后100分收尾,只A了第三题,后来发现这是一场普及组的卷子,心态要炸

转载于:https://www.cnblogs.com/si-rui-yang/p/9671329.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值