A:队列Q
我们给这些数字的一个下标,然后对下标进行操作即可,最终按下标排序输出。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5+5;
const int INF = 0x3f3f3f3f;
int n, p, s, e;
pair<int, int> a[MAXN];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
int t; scanf("%d", &t);
a[t].first= i;
a[t].second = t;
}
s = 0, e = n+1;
scanf("%d", &p);
while (p--)
{
char op[10]; int x;
scanf("%s%d", op, &x);
if (op[0] == 'F') a[x].first = s--;
else a[x].first = e++;
}
sort(a+1, a+1+n);
for (int i = 1; i <= n; i++)
printf("%d%c", a[i].second, i<n?' ':'\n');
return 0;
}
/*
4
4 2 1 3
3
FIRST 4
LAST 2
LAST 1
*/
B:矩阵
出题人的题解:Wannafly 挑战赛 19 参考题解
所以我们维护一个单调递增的队列即可,根据第二个和第三个条件删除队头元素。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 505;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int R, C, X, Y, Z;
ll a[MAXN][MAXN], zero[MAXN][MAXN], prefix[MAXN], cnt[MAXN], Q[MAXN];
int main()
{
scanf("%d%d%d%d%d", &R, &C, &X, &Y, &Z);
for (int i = 1; i <= R; i++)
{
for (int j = 1; j <= C; j++)
{
scanf("%lld", &a[i][j]);
zero[i][j] = zero[i-1][j] + int(a[i][j]==0);
a[i][j] += a[i-1][j];
}
}
ll ans = 0;
for (int i = 1; i <= R; i++)
{
for (int j = i; j <= R; j++)
{
if (j-i+1 > X) break;
prefix[0] = cnt[0] = 0;
int l = 0, r = 0;
Q[r++] = 0;
for (int k = 1; k <= C; k++)
{
prefix[k] = prefix[k-1] + a[j][k]-a[i-1][k];
cnt[k] = cnt[k-1] + zero[j][k]-zero[i-1][k];
while (l < r && (k-Q[l] > Y || cnt[k]-cnt[Q[l]] > Z)) l++;
while (l < r && prefix[Q[r-1]] >= prefix[k]) r--;
Q[r++] = k;
ans = max(ans, prefix[k]-prefix[Q[l]]);
}
}
}
printf("%lld\n", ans);
return 0;
}
/*
5 5 3 3 4
0 0 10 0 0
3 4 0 2 3
-1 3 0 -8 3
0 0 32 -9 3
3 0 45 3 0
*/