The 2019 Asia Yinchuan First Round Online Programming

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]数。

原文地址:https://www.cnblogs.com/Accpted/p/11440051.html