列表

详情


NC211598. 看比赛

描述

牛牛很喜欢看别人打比赛,尤其是看ACM。

有一天牛牛在观看一场ACM,不知不觉中,封榜了。但是牛牛心里清楚,这封榜的最后一个小时,这场ACM的参赛者肯定不能再多做超过一道题了。

牛牛是个好奇的人,所以他想知道将他们的切题数排序(如果切题数相同,则编号小者在前,否则切题多越靠前),最多有多少种可能的排行榜(两个排行榜不同当且仅当他们在某一位置的选手编号不同)。

然而这场ACM的题目太多了,选手也太多了,所以他想要结果对998244353取模。

输入描述

第一行一个 n 表示选手的数量

第二行 n 个数

a_i 表示封榜前编号 i 的选手切题数

输出描述

一行答案

示例1

输入:

3
1 2 2

输出:

5

说明:

编号序列分别为:
3 2 1
2 3 1
1 2 3
2 1 3
3 1 2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 203ms, 内存消耗: 25888K, 提交时间: 2020-09-25 22:31:22

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 998244353;
const int maxn = 1001001;
int f[maxn], g[maxn], h[maxn], sh[maxn], s[maxn], s2[maxn], sj[maxn], r[maxn], id[maxn];
struct node {
    int v, id;
    bool operator < (const node & a) const {
        return v < a.v || (v == a.v && id > a.id);
    }
} p[maxn];
int main(void) {
    //freopen("e.in","r",stdin);
    int n; scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&p[i].v), p[i].id=i;
    for (int i=n+1;i<=n+n;i++) p[i].v=p[i-n].v+1, p[i].id=i-n;
    sort(p+1,p+n+n+1);

    for (int i=1,tot=0;i<=2*n;i++) {
        if (!id[p[i].id]) id[p[i].id] = ++tot;
        else r[id[p[i].id]] = tot;
    }

//    for (int i=1;i<=n;i++) printf("%d ",r[i]); puts("");
    f[n] = g[n] = s[n] = s2[n] = 1;
    sj[n] = n;
    for (int i=n-1;i>=1;i--) {
        f[i] = (f[i+1] + (sh[i+2] - sh[r[i+1]+1] + mod)%mod)%mod;
        if (r[i] == i+1) h[i+1] = f[i+1];
        else if (r[i] >= i+2) {
            h[i+1] = (((f[i+1] + (sj[i+2]-sj[r[i]]+mod)%mod)%mod - (i+1)*(ll)(s2[i+2]-s2[r[i]]+mod)%mod + mod)%mod
                + (r[i]-(i+1))*(ll)g[r[i]]%mod)%mod;
        }
        sh[i+1] = (h[i+1] + sh[i+2])%mod;
        s[i] = (sh[max(i+2,r[i]+1)] - sh[r[i+1]+1] + mod)%mod;
        if (r[i] == i) g[i] = f[i];
        else g[i] = (g[i+1] + s[i])%mod;
        s2[i] = (s[i] + s2[i+1])%mod;
        sj[i] = (i*(ll)s[i]%mod + sj[i+1])%mod;
//        printf("f[%d] = %d\n",i,f[i]);
//        printf("h[%d] = %d\n",i+1,h[i+1]);
//        printf("g[%d] = %d\n",i,g[i]);
//        printf("s[%d] = %d\n",i,s[i]);
    }
    int ans = (f[1] + (sh[2] - sh[r[1]+1] + mod)%mod)%mod;
    printf("%d\n", ans);
    return 0;
}

C++(clang++11) 解法, 执行用时: 130ms, 内存消耗: 6288K, 提交时间: 2021-02-08 10:43:10

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5,mod=998244353;
int n,f[N];
struct node
{
    int x,id;
    bool operator<(const node&o)const
    {
        return x==o.x?id<o.id:x>o.x;
    }
}a[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i].x),a[i].id=i;
    sort(a+1,a+1+n);
    f[0]=1;
    for(int i=1,l=1,r=1;i<=n;i++)
    {
        f[i]=(f[i]+f[i-1]*2%mod)%mod;
        r=max(r,i);
        while(r<=n&&(a[r].x==a[i].x||a[r].x==a[i].x-1&&a[r].id<a[i].id)) r++;
        while(l<i&&(a[l].x>a[i].x+1||a[l].x==a[i].x+1&&a[l].id<a[i].id)) l++;
        f[r-1]=(f[r-1]+mod-f[l-1])%mod;
    }
    printf("%d\n",f[n]);
}

上一题