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;
}
posted @ 2022-10-22 17:43  zyy2001  阅读(52)  评论(0编辑  收藏  举报