为什么你们代码那么清奇俊秀啊
为什么暴力都过了啊
为什么我这么菜啊...
请忽略上面的话 ==
CF: https://codeforces.com/problemset/problem/85/D
Luogu: https://www.luogu.com.cn/problem/CF85D
你要维护一个集合,支持加入或删除一个数(保证任意时刻元素都没有重复,且待删除的数一定在集合里)
然后每次询问,你要回答排序后(从小到大)下标(从1开始)(\% 5=3)的所有数的和。
所有数为正整数且不超过(10^9)
下面大概是一个不要动脑子的做法(
首先建一棵权值线段树,然后每个节点维护几个东西
- (cnt),即这个节点所代表的值域区间里有多少个数
- (s[0..4]),(s[i])表示这个节点内的所有数排序后下标(\% 5=i)的数的和
上面两个东西随便算算就好了(具体看代码...)
然后(10^9)炸了...那就动态开点呗...
非常无脑且好写的代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
struct node {
int lc, rc;
ll s[5]; int cnt;
} t[N * 40];
int rt = 0, siz = 0;
void pushup(int x) {
int lc = t[x].lc, rc = t[x].rc, ls = t[lc].cnt;
// 讨论左右节点
for (int i = 0; i < 5; i++) t[x].s[i] = t[lc].s[i];
for (int i = 0; i < 5; i++) t[x].s[(i + ls) % 5] += t[rc].s[i]; // 维护s[0..4]
t[x].cnt = t[lc].cnt + t[rc].cnt;
}
void insert(int &x, int l, int r, int p, int v) { // p插入的数的值,v=-1删除,v=1加入
if (!x) x = ++siz; // 动态开点
if (l == r) {
t[x].cnt += v;
t[x].s[1] += 1ll * l * v;
return;
}
int mid = (l + r) >> 1;
if (p <= mid) insert(t[x].lc, l, mid, p, v);
else insert(t[x].rc, mid + 1, r, p, v);
pushup(x);
}
int main() {
char s[23];
int _; for (scanf("%d", &_); _; _--) {
scanf("%s", s);
if (s[0] == 's') printf("%lld
", t[rt].s[3]);
else {
int d = s[0] == 'd' ? -1 : 1, v;
scanf("%d", &v);
insert(rt, 1, 1e9, v, d);
}
}
return 0;
}