The 2019 Asia Yinchuan First Round Online Programming
Maximum Element In A Stack
Rolling The Polygon
Caesar Cipher
Take Your Seat
Moving On
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,k,q;
int dp[210][210][210];
int d[210],id[210];
bool cmp(int x,int y) {
return d[x] < d[y];
}
int main() {
int _,ca=0;
scanf("%d", &_);
while (_--) {
memset(dp, 0x3f, sizeof(dp));
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++) {
scanf("%d", &d[i]);
id[i] = i;
}
sort(id + 1, id + 1 + n, cmp);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
scanf("%d", &dp[0][i][j]);
}
}
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dp[k][i][j] = min(dp[k - 1][i][j], dp[k - 1][i][id[k]] + dp[k - 1][id[k]][j]);
}
}
}
printf("Case #%d:\n",++ca);
for (int i = 1; i <= q; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
int k = 0;
for (int i = 1; i <= n; i++) {
if (d[id[i]] <= w) {
k = i;
}
}
printf("%d\n", dp[k][u][v]);
}
}
return 0;
}
Continuous Intervals
给出n个数的序列。问序列中有多少个区间满足,排序完之后任意两个相邻的数之差不大于1。
题解:
用max表示区间最大值,min表示区间最小值,cnt表示区间数字的种数。那么问题转化成求max-min=cnt+1的区间数。
用线段树维护每个区间的max-min-cnt最小值及最小值的个数,不用单独维护max,min和cnt。注意max-min >= cnt+1.
从1~n枚举R。对于每个枚举的R,更新以R为后缀的[L,R]区间的max-min-cnt值。
对于max和min可以用单调栈维护,max和min对max-min-cnt的贡献采用区间加减的形式而不是区间覆盖。
对于cnt可以用一个vis[]数组维护上一次的出现位置,然后也进行区间加减。数据是1e9的,vis[]数组可以离散一下或者用map代替。
最后对于每一个枚举的R,统计max-min-cnt的值为-1的[L,R]数。