vjudge上面的题当天是我负责讲题所以写了一下博客,优先队列永远的敌人,一直没太整清楚
前置知识
倍增
//倍增
//给定一个数列,共有n个正数,现在有m次询问,每次询问给出一个t,求满足最小的k使得从第一个数到第k个数之和小于等于t;
#include<cstdio>
#include<iostream>
using namespace std;
const int maxn =1e5+10;
int n,m;
int a[maxn];
int main()
{
cin >>n>>m;
for(int i=1;i<=n;i++)
{
cin >>a[i];
a[i] += a[i-1];
}
while(m--)
{
int t;
cin >>t;
int k=0,p=1;
while(p)
{
if(k+p>n)break;
if(a[k+p] <= t)k+=p,p*=2;
else p/=2;
}
cout <<k<<endl;
}
return 0;
}
A - 切蛋糕
思路
推方程
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int sum[N], dq[N]; //dq表示模拟的一个双端队列,存的是坐标
int ans = -0x3fff;
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1, x; i <= n; i++) {
scanf("%d", &x);
sum[i] = sum[i - 1] + x;
}
int l = 1, r = 1;
for (int i = 1; i <= n; i++) { //枚举i
//更新答案
while (dq[l] < i - m) {
l++;
}
ans = max(ans, sum[i] - sum[dq[l]]);
//如果存在递减的情况就删掉
while (l <= r && sum[dq[r]] >= sum[i]) {
r--;
}
dq[++r] = i;
}
printf("%d\n", ans);
return 0;
}
B - 好消息,坏消息
思路
因为是一个环状的,所以扩大一倍数组 用sum[q[l]] - sum[k - 1] >= 0 表示没有<0的情况 -3 5 1 2 -3 5 12
-3 5 1 2 -3 5 1 2
-3 2 3 5 2 7 8 10
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 5;
int a[N], sum[N], q[N];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i + n] = a[i];
}
int m = n << 1;
for (int i = 1; i <= m; i++) {
sum[i] = sum[i - 1] + a[i];
}
int l = 1, r = 1, ans = 0;
q[1] = 1;
for (int i = 1; i <= m - 1; i++) {
while (q[l] < i - n + 1)
l++; //让头子在区间内
//存在递增的情况
while (l <= r && sum[i] <= sum[q[r]])
r--;
q[++r] = i;
int k = i - n + 1;
if (k > 0 && sum[q[l]] - sum[k - 1] >= 0) {
ans++;
}
}
printf("%d\n", ans);
return 0;
}
C - 良好的感觉
思路
枚举i,ans[i]表示以a[i]为最小的子段的最大和
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
long long a[N], sum[N], ans[N], q[N];
long long Anss;
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
int r = 0;
q[r] = 0;
//3 1
//q : 3 1
for (int i = 1; i <= n; i++) {
//查看是否可以更新之前的决策
while (a[q[r]] >= a[i]) {
ans[q[r]] += sum[i - 1] - sum[q[r]];
r--;
}
//加入决策
ans[i] = sum[i] - sum[q[r]];
q[++r] = i;
}
for (int i = 1; i <= n; i++) {
Anss = max(Anss, (long long)ans[i] * a[i]);
}
printf("%lld\n", Anss);
return 0;
}
D - 机器翻译
思路
简单模拟
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
deque<int> dq;
int a[N];
bool inq[N];
int main() {
int m, n;
scanf("%d%d", &m, &n);
int ans = 0;
for (int i = 1, x; i <= n; i++) {
scanf("%d", &x);
if (inq[x])
continue;
ans++;
if (dq.size() < m) {
inq[x] = 1;
dq.push_back(x);
} else {
inq[dq.front()] = 0;
dq.pop_front();
dq.push_back(x);
inq[x] = 1;
}
}
printf("%d\n", ans);
return 0;
}
标签:const,23,int,sum,寒假,ans,using,include,集训
From: https://www.cnblogs.com/oddpointa/p/17041502.html