牛客國慶day3

hesorchen發表於2020-10-03

Leftbest

給定一個序列,如果在 a i a_i ai之前有 a j < a i a_j<a_i aj<ai,那麼找到最小的 a j a_j aj,把所有這樣的 a j a_j aj相加。

4 
2 1 4 3

例如樣例就是1前面的2,加上3前面的4。答案為6。

比賽的時候只想到了權值線段樹解法,離散化之後維護區間最小值:

struct node
{
    int l, r, k, minn;
} tr[400040];

inline void update(int k)
{
    tr[k].minn = min(tr[k * 2].minn, tr[k * 2 + 1].minn);
}

void build(int k, int l, int r)
{
    tr[k].l = l;
    tr[k].r = r;
    if (l == r)
    {
        tr[k].minn = INF;
        return;
    }
    int mid = l + r >> 1;
    build(k * 2, l, mid);
    build(k * 2 + 1, mid + 1, r);
    update(k);
}

void insert(int k, int w)
{
    if (tr[k].l == tr[k].r && tr[k].l == w)
    {
        tr[k].minn = w;
        return;
    }
    int mid = tr[k].l + tr[k].r >> 1;
    if (w <= mid)
        insert(k * 2, w);
    else
        insert(k * 2 + 1, w);
    update(k);
}

int query(int k, int l, int r)
{
    if (tr[k].l == l && tr[k].r == r)
        return tr[k].minn;
    int mid = tr[k].l + tr[k].r >> 1;
    if (r <= mid)
        return query(k * 2, l, r);
    else if (l > mid)
        return query(k * 2 + 1, l, r);
    else
        return min(query(k * 2, l, mid), query(k * 2 + 1, mid + 1, r));
}

int b[100010];
int c[100010];
int a2[100010];
int b2[100010];
struct node2
{
    int a, c;
    bool operator<(node2 temp) const
    {
        return c < temp.c;
    }
} p[100010];

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &p[i].a), b[i] = p[i].a;
    sort(b + 1, b + 1 + n);
    int len = unique(b + 1, b + 1 + n) - b;
    for (int i = 1; i <= n; i++)
        c[i] = p[i].c = lower_bound(b + 1, b + 1 + n, p[i].a) - b;
    sort(p + 1, p + 1 + n);
    for (int i = 1; i <= n; i++)
    {
        a2[i] = p[i].a;
        b2[i] = p[i].c;
    }
    build(1, 1, 100005);
    long long ans = 0;
    for (int i = 1; i <= n; i++)
    {
        insert(1, c[i]);
        int temp = query(1, c[i] + 1, 100005);
        if (temp == INF)
            continue;
        int pos = lower_bound(b2 + 1, b2 + 1 + n, temp) - b2;
        ans += a2[pos];
    }
    printf("%lld\n", ans);
    return 0;
}

碼量挺大的,看到他們的過題速度就知道事情不簡單,其實直接用set存前面所有數,二分查詢即可:

set<int> st;
int main()
{
    int n;
    long long ans = 0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        int temp;
        scanf("%d", &temp);
        if (st.upper_bound(temp) != st.end())
            ans += *st.upper_bound(temp);
        st.insert(temp);
    }
    printf("%lld\n", ans);
    return 0;
}

Flowers

n n n種花,每種花有 a i a_i ai種, m m m種不同的話可以組成一束花,問最多可以組成多少種花。

賽時用一個小頂堆一個大頂堆維護第k大,wa+tle七發之後瞎猜了一個結論改改過了。賽後發現別人都是二分,(明天一定補。

priority_queue<int, vector<int>, greater<int>> q1;
priority_queue<int> q2;
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        while (q1.size())
            q1.pop();
        while (q2.size())
            q2.pop();
        int n, m;
        read(n);
        read(m);
        for (int i = 1; i <= n; i++)
        {
            int temp;
            read(temp);
            q1.push(temp);
        }
        if (m > n)
        {
            printf("0\n");
            continue;
        }
        while (q1.size() > m)
        {
            int temp = q1.top();
            q1.pop();
            q2.push(temp);
        }
        long long ans = 0;
        while (q1.top() > 1)
        {
            int k = q1.top() - 1;
            ans += k;
            while (q1.size())
            {
                int temp = q1.top();
                q1.pop();
                temp -= k;
                q2.push(temp);
            }
            while (q1.size() < m)
            {
                int temp = q2.top();
                q2.pop();
                q1.push(temp);
            }
        }
        while (q1.top())
        {
            int k = q1.top();
            ans += k;
            while (q1.size())
            {
                int temp = q1.top();
                q1.pop();
                temp -= k;
                q2.push(temp);
            }
            while (q1.size() < m)
            {
                int temp = q2.top();
                q2.pop();
                q1.push(temp);
            }
        }
        printf("%lld\n", ans);
    }
    return 0;
}