牛客练习赛109 B D

浅浅vp了一下

牛客练习赛109_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)

B

题意:

思路:

考虑尺取法找出最长的超现实子串

当右边一直满足条件的时候就r++,然后条件用k维护就行,统计最大值

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <map>
#define int long long
using namespace std;
using i64 = long long;
const int mxn=1e6+10;
const int mxe=1e6+10;
const int mod=1e9+7;

int n;
int a[mxn];
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int r=1,ans=0;
    for(int l=1;l<=n;l++){
        int k=1;
        r=l+1;
        while(r<=n&&a[r]==a[l]+k){
            r++;
            if(k>0) k=-k;
            else k--,k=-k;
        }
        r--;
        ans=max(ans,r-l+1);
    }
    cout<<ans<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int __=1;//cin>>__;
    while(__--)solve();return 0;
}

D

题意:

思路:

贪心,直接从贡献入手,去计算贡献

设未知数 x,y

不妨设x<y,此时贡献为x*y

然后x+m,y-m,此时贡献为 xy+(y-x)*m-m*m

那么去考虑 (y-x)*m-m*m和0比较

y>x+m时贡献为正,否则就是负

因此策略就是每次拿出最大值和最小值操作,操作k次

我赛时思考止步于次,想用优先队列维护但是失败了

线段树维护很妙啊

这道题里我们需要维护区间最小/大值下标和整个区间的积

因为是整个区间,因此直接修改a数组里面的值就行了

那只需要写区间最值下标就行

当我们在确定我们需要什么数据结构时,先去确定我们需要维护的是哪些量

Code:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <map>
#include <queue>
#define int long long
using namespace std;
using i64 = long long;
const int mxn=1e6+10;
const int mxe=1e6+10;
const int mod=1e9+7;
struct ty{
    int mx,mi;
}tree[mxe<<2];

int n,m,k;
int a[mxn];
void pushup(int rt){
    tree[rt].mi=(a[tree[rt<<1].mi]<a[tree[rt<<1|1].mi])?tree[rt<<1].mi:tree[rt<<1|1].mi;
    tree[rt].mx=(a[tree[rt<<1].mx]>a[tree[rt<<1|1].mx])?tree[rt<<1].mx:tree[rt<<1|1].mx;
}
void modify(int rt,int l,int r,int x,int cmd){
    if(l==r) return;
    int mid=l+r>>1;
    if(x<=mid) modify(rt<<1,l,mid,x,cmd);
    else modify(rt<<1|1,mid+1,r,x,cmd);
    pushup(rt);
}
void build(int rt,int l,int r){
    if(l==r){
        tree[rt].mi=tree[rt].mx=l;
        return;
    }
    int mid=l+r>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}
void solve(){
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) cin>>a[i];
    build(1,1,n);
    while(k--){
        if(a[tree[1].mx]-a[tree[1].mi]<=m) break;
        a[tree[1].mx]-=m,modify(1,1,n,tree[1].mx,1);
        a[tree[1].mi]+=m,modify(1,1,n,tree[1].mi,-1);
    }
    int ans=1;
    for(int i=1;i<=n;i++) ans=(ans*a[i])%mod;
    cout<<ans<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int __=1;//cin>>__;
    while(__--)solve();return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值