CF #546 D.E

D

coun[i]表示[i]这个数右边有多少个数j能和他组成题中所给的二元组(i,j)

如果一个数的coun[i]=n-i-ans 那么说明他可以与最后一个交换 同时不计算贡献 因为它是向右走的 对左边没有贡献

#include<bits/stdc++.h>
using namespace std;
int num[300005];
vector<int> f[300005];
int coun[300005];
int main() {
        int n, m;
        scanf("%d %d", &n, &m);
        for (int i = 1; i <= n; i++) {
                scanf("%d", &num[i]);
        }
        int a, b;
        for (int i = 1; i <= m; i++) {
                scanf("%d  %d", &a, &b);
                f[b].push_back(a);
        }
        int ans = 0;
        for (int i = 0; i < f[num[n]].size(); i++) {
                int now = f[num[n]][i];
                coun[now]++;
        }
        for (int i = n - 1; i >= 1; i--) {
                int now = num[i];
                if (coun[now] == n - i - ans) {
                        ans++;
                } else {
                        for (int v : f[now]) {
                                coun[v]++;
                        }
                }
        }
        printf("%d\n", ans);
        return 0;
}

E

令k[i]的前缀和为c[i] 则题目中的要求Ai+1>=Ai+ki两边同时减去c[i]可以变成Ai+1-c[i]>=Ai-c[i-1] 再令b[i]=Ai-c[i-1] 变成b[i+1]>=b[i]

询问中的求和就直接求b[i]的和再补上减去的c[i]即可 单点修改操作则是二分求第一个大于等于b[i]+x的位置再区间修改即可

 

posted @ 2019-03-20 09:46  Aragaki  阅读(218)  评论(0编辑  收藏  举报