线段树,每个点记录该点出现的次数,对于l,r的更新,
找到l所对应的数,找到r对应的数,单点更新这两个数,然后区间更新他们之间的数。
查找也是一样。
#include <cstdio> #include <cstring> #define max(a, b) ((a) > (b)) ? (a) : (b) #define min(a, b) ((a) > (b)) ? (b) : (a) const int maxn = 400007; struct Seg { int left, right; int lazy; long long max_num, sum; }; struct Seg seg[maxn * 4]; void pushUp(int order) { seg[order].max_num = max(seg[order * 2].max_num, seg[order * 2 + 1].max_num); seg[order].sum = seg[order * 2].sum + seg[order * 2 + 1].sum; } void pushDown(int order) { if (seg[order].lazy > 1) { seg[order * 2].sum *= seg[order].lazy; seg[order * 2 + 1].sum *= seg[order].lazy; seg[order * 2].max_num *= seg[order].lazy; seg[order * 2 + 1].max_num *= seg[order].lazy; seg[order * 2].lazy *= seg[order].lazy; seg[order * 2 + 1].lazy *= seg[order].lazy; seg[order].lazy = 1; } } void init(int order, int left, int right) { int mid = (left + right) >> 1; seg[order].left = left; seg[order].right = right; seg[order].lazy = 1; if (left == right) { seg[order].max_num = 1; seg[order].sum = 1; return ; } init(order * 2, left, mid); init(order * 2 + 1, mid + 1, right); pushUp(order); } void update(int order, int left, int right) { if (right < left) { return ; } int mid = (seg[order].left + seg[order].right) >> 1; if (left <= seg[order].left && right >= seg[order].right) { seg[order].lazy *= 2; seg[order].sum *= 2; seg[order].max_num *= 2; return ; } pushDown(order); if (right <= mid) { update(order * 2, left, right); } else if (left > mid) { update(order * 2 + 1, left, right); } else { update(order * 2, left, mid); update(order * 2 + 1, mid + 1, right); } pushUp(order); } long long querySum(int order, int left, int right) { if (right < left) { return 0; } int mid = (seg[order].left + seg[order].right) >> 1; if (left <= seg[order].left && right >= seg[order].right) { return seg[order].sum; } pushDown(order); if (right <= mid) { return querySum(order * 2, left, right); } else if (left > mid) { return querySum(order * 2 + 1, left, right); } else { return querySum(order * 2, left, mid) + querySum(order * 2 + 1, mid + 1, right); } } long long query(int order, int left, int right) { if (right < left) { return 0; } int mid = (seg[order].left + seg[order].right) >> 1; if (left <= seg[order].left && right >= seg[order].right) { return seg[order].max_num; } pushDown(order); if (right <= mid) { return query(order * 2, left, right); } else if (left > mid) { return query(order * 2 + 1, left, right); } else { long long max_1 = query(order * 2, left, mid); long long max_2 = query(order * 2 + 1, mid + 1, right); if (max_1 > max_2) { return max_1; } else { return max_2; } } } void updateSingle(int order, int loc, long long val) { int mid = (seg[order].left + seg[order].right) >> 1; if (seg[order].left == seg[order].right) { seg[order].sum += val; seg[order].max_num += val; return ; } pushDown(order); if (loc <= mid) { updateSingle(order * 2, loc, val); } else { updateSingle(order * 2 + 1, loc, val); } pushUp(order); } int findLoc(int order, long long val) { if (seg[order].left == seg[order].right) { return order; } pushDown(order); if (val > seg[order * 2].sum) { return findLoc(order * 2 + 1, val - seg[order * 2].sum); } else { return findLoc(order * 2, val); } } int n, m; int main() { // freopen("in.txt", "r", stdin); int test_case; int ncase = 1; scanf("%d", &test_case); while (test_case--) { printf("Case #%d:\n", ncase); ncase++; scanf("%d%d", &n, &m); init(1, 1, n); for (int i = 1; i <= m; i++) { char temp[10]; long long l, r; scanf("%s", temp); scanf("%I64d%I64d", &l, &r); int order_1 = findLoc(1, l); int order_2 = findLoc(1, r); if (temp[0] == 'D') { if (order_1 == order_2) { updateSingle(1, seg[order_1].left, r - l + 1); } else { long long pre_sum = querySum(1, 1, seg[order_1].left); long long temp = querySum(1, 1, seg[order_2].left - 1); updateSingle(1, seg[order_1].left, pre_sum - l + 1); updateSingle(1, seg[order_2].left, r - temp); update(1, seg[order_1].left + 1, seg[order_2].left - 1); } } else { long long ans = 0; if (order_1 == order_2) { ans = (r - l + 1); } else { long long pre_sum = querySum(1, 1, seg[order_1].left); ans = pre_sum - l + 1; pre_sum = querySum(1, 1, seg[order_2].left - 1); ans = max(ans, r - pre_sum); pre_sum = query(1, seg[order_1].left + 1, seg[order_2].left - 1); ans = max(ans, pre_sum); } printf("%I64d\n", ans); } } } return 0; }