hdu4288 Coder 2012成都网络赛 A题
题意:往集合里面添加删除数,集合中的数是按从小到大排列的,询问下标模5等于3的数的和。
解法:预先把所有出现的数离散化,建立一颗线段树,线段树每个节点存储这样几个值,f[i]表示当前这个节点表示的区间内出现的那些下标模5等于i的和,维护sz表示该段区间内出现的数的个数,没有出现的地方f为0。考虑合并两段区间,即如何由两个儿子节点推出父亲节点,考虑父亲的f[i],等于左儿子的f[i] + 右儿子的f[x], x与左儿子的sz有关,即(x + sz %5) %5 = i ;可解出x。如此查询只需要查询1号节点的f[3]即可,
可以先考虑一棵平衡树,每次由儿子更新父亲也是如此,然后考虑线段树,线段树不过多了几个空的位置而已,而且空的位置我们不计入即可。
/* edited by oshixiaoxiliu */ #define maxn 100005 struct node { int l,r; int sz; i64 f[5]; int mid() { return (l + r ) /2 ; } }; node tt[maxn * 3 ]; struct node1 { int id ; i64 x; }; node1 ml[maxn]; void push_up(int root ) { int sz ; sz = tt[root * 2].sz; tt[root].sz = tt[root * 2].sz + tt[root * 2 + 1].sz; for(int i = 0 ; i < 5 ; i ++ ) tt[root].f[i] = tt[root * 2].f[i] + tt[root * 2 + 1 ].f[(i + 5 - sz % 5 ) % 5]; return ; } void build(int root ,int l,int r ) { tt[root].l = l ; tt[root].r = r ; tt[root].sz = 0 ; for(int i = 0; i < 5; i ++ ) tt[root].f[i] = 0 ; if(l == r ) return ; int mid = tt[root].mid(); build(root * 2 , l , mid ); build(root * 2 + 1 , mid + 1 , r); return ; } void update(int root ,int pos ,i64 vv) { if(tt[root].l == tt[root].r ) { if(vv == 0 ) { tt[root].sz = 0 ; for(int i = 0; i < 5; i ++ ) tt[root].f[i] = 0 ; } else { tt[root].sz = 1 ; for(int i = 0 ; i < 5 ;i ++ ) tt[root].f[i] = 0 ; tt[root].f[1] = vv; } return ; } int mid = tt[root].mid(); if(pos <= mid ) update(root * 2 , pos , vv); if(pos > mid ) update(root * 2 + 1 , pos , vv); push_up(root); } int num; i64 b[maxn]; int pos[maxn]; char str[10]; int main() { int x; int n ; while(scanf("%d",&n)!=EOF) { num = 0 ; for(int i = 1 ;i <= n ; i ++ ) { scanf("%s",str); if(str[0] == 'a') { ml[i].id = 1; scanf("%I64d",&ml[i].x); b[num++] = ml[i].x; } else if(str[0] == 'd') { ml[i].id = 2 ; scanf("%I64d",&ml[i].x); b[num++] = ml[i].x; } else { ml[i].id = 3; } } sort(b ,b + num); int pos; num = unique(b,b+num) - b; build(1,1,num); for(int i = 1; i <= n ; i ++ ) if(ml[i].id != 3) { pos = lower_bound(b , b + num , ml[i].x) - b + 1 ; if(ml[i].id == 1 ) update(1,pos,ml[i].x); else update(1,pos,0); } else { printf("%I64d\n",tt[1].f[3]); } } return 0; }
--------------oshixiaoxiliu

浙公网安备 33010602011771号