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: ",++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 ", 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]数。