2021 CCPC 新疆省赛
比赛链接
2021 CCPC 新疆省赛
Problem B. sophistry
小k有n天在群里嘲笑管理员,小K在第i天嘲笑管理员,管理员会受到ai的伤害,如果这个伤害超过m值,管理员会将小k禁言d天,问小k能对管理员造成的最大伤害是多少
解题思路
dp
逆序考虑:
-
状态表示:\(f[i]\) 表示 \(i\sim n\) 这些天中的最大伤害
-
状态计算:
-
- \(a[i]<=m\) 时,\(f[i]=f[i+1]+m\)
-
- \(a[i]>m\) 时,\(f[i]=max(f[i+1],f[i+d+1]])\)
-
时间复杂度:\(O(n)\)
代码
// Problem: Problem B. sophistry
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/43472/B
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=2e5+5;
int n,d,m,a[N];
LL f[N];
int main()
{
cin>>n>>d>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=n;i;i--)
if(a[i]<=m)f[i]=f[i+1]+a[i];
else
f[i]=max(f[i+1],a[i]+f[i+d+1]);
cout<<f[1];
return 0;
}
Problem D.maxsum
给一个长度为n的数组a,求前w大的区间和的值。
解题思路
思维
先用大根堆存下最大的数及其左端点 \(l\) 和右端点 \(r\),每次弹元素时都是当前所有子区间和的最大值,将 \([l+1,r]\) 和 \([l,r-1]\) 入队,次大值此时一定在队列中,对于队列中的所有区间,假设对头区间为当前最大区间和,要找一个次大区间和,则该区间也可能在队列中,也可能是队头区间 \([l,r]\) 的两个子区间 \([l+1,r]\) 或 \([l,r-1]\),弹 \(w\) 次即可得到前 \(w\) 大的区间和
- 时间复杂度:\(O(wlogw)\)
代码
// Problem: Proble***xsum
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/43472/D
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
const int N=1e5+5;
int n,w;
LL s[N];
struct A
{
LL w;
int l,r;
bool operator<(const A &o)const
{
return w<o.w;
}
};
int main()
{
cin>>n>>w;
for(int i=1;i<=n;i++)cin>>s[i],s[i]+=s[i-1];
priority_queue<A> q;
q.push({s[n],1,n});
vector<LL> res;
unordered_set<LL> S;
S.insert(N+n);
while(res.size()<w)
{
auto t=q.top();
q.pop();
res.pb(t.w);
int l=t.l,r=t.r;
if(l+1<=r&&!S.count((l+1)*N+r))q.push({s[r]-s[l],l+1,r}),S.insert((l+1)*N+r);
if(l<=r-1&&!S.count(l*N+r-1))q.push({s[r-1]-s[l-1],l,r-1}),S.insert(l*N+r-1);
}
for(int i=0;i<w;i++)cout<<res[i]<<' ';
return 0;
}