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的位置再区间修改即可