求调 & 题面疑问
查看原帖
求调 & 题面疑问
507348
__vector__楼主2025/1/2 17:16

我只过了样例和 #21。

关于我的做法

做法是枚举起点,然后计算 dpidp_i 代表前 ii 个单位时间能获得的最大收益。

单调队列优化,每次弹出所有满足 ijpi-j \ge pjj

关于题面疑问

同一条道路上的金币是否会消失?
比如说时刻 1 出现了 33 个,时刻 22 出现了 44 个,那么如果时刻 22 收集,是收集 44 个吗?

求助 /bx /bx /bx

#include <bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define REP(i,a,b) for(int i=a;i>=b;i--)
#define pb push_back
#define mkpr make_pair
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
template<class T>
void ckmx(T& a,T b){
    a=max(a,b);
}
template<class T>
void ckmn(T& a,T b){
    a=min(a,b);
}
template<class T>
T gcd(T a,T b){
    return !b?a:gcd(b,a%b);
}
template<class T>
T lcm(T a,T b){
    return a/gcd(a,b)*b;
}
#define gc getchar()
#define eb emplace_back
#define pc putchar
#define ep empty()
#define fi first
#define se second
#define pln pc('\n');
template<class T>
void wrint(T x){
    if(x<0){
        x=-x;
        pc('-');
    }
    if(x>=10){
        wrint(x/10);
    }
    pc(x%10^48);
}
template<class T>
void wrintln(T x){
    wrint(x);
    pln
}
template<class T>
void read(T& x){
    x=0;
    int f=1;
    char ch=gc;
    while(!isdigit(ch)){
        if(ch=='-')f=-1;
        ch=gc;
    }
    while(isdigit(ch)){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=gc;
    }
    x*=f;
}
const int maxn=1005;
int n,m,p;
ll dp[maxn*2];
ll reward[maxn][2*maxn];
ll cost[maxn];
/*
注意到,确定起点之后,只需要根据时间就可以得到位置
考虑枚举起点。  
然后,dp[i] 代表前 i 个单位的时间走完的最大收益
枚举时间,每次新加入 len=1 的一个单位,同时此前已经加入的,代价全部加上一个定值
同时,将 i-j>p 的删掉
*/
int lst(int i,int dis){
    return ((i-1-dis)%n+n)+1;
}
void solve(int id_of_test){
	read(n);
    read(m);
    read(p);
    FOR(i,1,n){
        FOR(j,1,m){
            read(reward[i][j]);
        }
    }
    FOR(i,1,n){
        read(cost[i]);
    }
    ll ans=-1e18;
    FOR(s,1,n){
        // s = 起点位置
        FOR(i,1,m+p)dp[i]=-1e9;
        deque<pll> rem;// fi:代价,se:终止时间
        ll add=0;
        FOR(time,1,m+p){//需要注意,这个得扩展
            int nw_pos=(s-1+time-1)%n+1;// 现在走到了哪个点
            while(!rem.empty()&&time-rem.front().se>=p)rem.pop_front();
            add+=reward[nw_pos][time];
            ll nw=dp[time-1]+reward[nw_pos][time]-cost[nw_pos]-add;
            while(!rem.empty()&&nw>=rem.back().fi)rem.pop_back();
            rem.push_back(mkpr(nw,time));
            dp[time]=rem.front().fi+add;
        }
        ckmx(ans,*max_element(dp+1,dp+m+p+1));
    }
    printf("%lld\n",ans);
}
int main()
{
	int T;
	T=1;
	FOR(_,1,T){
		solve(_);
	}
	return 0;
}

2025/1/2 17:16
加载中...