題意:下標模5等於3的數的和。
題解:
可以這樣,線段樹的每個節點存一個數組 sum[5],表示當前節點覆蓋的區間中,從左到有編號,模 5 為 0,1,2,3,4的所有數的和
每個節點再儲存一個當前節點所包含的區間中有多少個數的資訊:cnt。那麼:
添加的時候就是在相應的位置把整數加進去,並把 cnt+1
刪除的時候就是在相應的位置賦值為 0,並把 cnt-1
關於 pushUp 的問題,我們可以這樣考慮:
父親的 cnt 肯定是兩個兒子的 cnt 的和
父親的 sum 肯定賦初值為 左兒子 的 sum
右兒子的 sum[i] 對應的是父親的 sum[(i+Lson.cnt)%5]
#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define MAXN 100009#define L(u) (u<<1)#define R(u) (u<<1|1)#define lint __int64struct NODE{ lint sum[5]; int l, r, cnt;} node[MAXN*3];int num[MAXN], val[MAXN], n; //num[0]記錄num的個數char oper[MAXN][5];void build(int u, int l, int r){ node[u].l = l; node[u].r = r; node[u].cnt = 0; for(int i = 0; i < 5; i++) node[u].sum[i] = 0; if(node[u].l == node[u].r) return; int mid = (l + r) >> 1; build(L(u), l, mid); build(R(u), mid + 1, r);}void pushUp(int u){ node[u].cnt = node[L(u)].cnt + node[R(u)].cnt; int x = node[L(u)].cnt; for(int i = 0; i < 5; i++) node[u].sum[i] = node[L(u)].sum[i]; for(int i = 0; i < 5; i++) node[u].sum[(x+i)%5] += node[R(u)].sum[i];}void update(int u, int index, int flag) //flag=1表示add,flag=-1表示del{ if(node[u].l == index && node[u].r == index) { node[u].cnt = 0; for(int i = 0; i < 5; i++) node[u].sum[i] = 0; if(flag == 1) { node[u].sum[1] = num[index]; node[u].cnt = 1; } return; } int mid = (node[u].l + node[u].r) >> 1; if(index <= mid) update(L(u), index, flag); else update(R(u), index, flag); pushUp(u);}int bfind(int l, int r, int key){ int mid; while(l < r) { mid = (l + r) >> 1; if(num[mid] == key) return mid; else if(num[mid] < key) l = mid + 1; else r = mid; } if(num[l] == key) return l; return r;}int main(){ while(scanf("%d", &n) != EOF) { int i, j; num[0] = 0; for(i = 1; i <= n; i++) { scanf("%s", oper[i]); if(oper[i][0] != 's') { scanf("%d", &val[i]); num[++num[0]] = val[i]; } } sort(num+1, num+1+num[0]); for(j = 1, i = 2; i <= num[0]; i++) if(num[j] != num[i]) num[++j] = num[i]; num[0] = j; build(1, 1, num[0]); for(i = 1; i <= n; i++) { if(oper[i][0] == 's') printf("%I64d\n", node[1].sum[3]); else if(oper[i][0] == 'a') { int index = bfind(1, num[0], val[i]); update(1, index, 1); } else { int index = bfind(1, num[0], val[i]); update(1, index, -1); } } } return 0;}