HDU 4288 Coder(线段树+离线处理+离散化)

 

题目大意

 

给了 n(1≤n≤100000 个操作,每个操作要么是在集合中添加一个整数(在区间 [1, 109] 中,且保证不在集合中),要么是删除一个整数(保证在集合中),还有一个操作 sum,询问的是当前集合中,所有元素从小到大排列好之后,下标除以 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],以此作为更新的依据

每一个求和的询问,直接输出根节点的 sum[3] 就行

 

参考代码

HDU 4288
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <map>
 7 
 8 using namespace std;
 9 
10 typedef long long LL;
11 const int N=100006;
12 
13 struct data
14 {
15     int val, fg;
16 } op[N];
17 int n;
18 char hehe[10];
19 map <int, int> ihash;
20 vector <int> haha;
21 
22 struct Interval_Tree
23 {
24     struct node
25     {
26         int s, t, cnt;
27         LL sum[5];
28         void init(int L, int R)
29         {
30             s=L, t=R, cnt=0;
31             for(int i=0; i<5; i++) sum[i]=0;
32         }
33     } T[N<<2];
34 
35     void build(int id, int L, int R)
36     {
37         T[id].init(L, R);
38         if(L==R) return;
39         int mid=(L+R)>>1;
40         build(id<<1, L, mid);
41         build(id<<1|1, mid+1, R);
42     }
43 
44     void pushUp(node &x, node &L, node &R)
45     {
46         x.s=L.s, x.t=R.t, x.cnt=L.cnt+R.cnt;
47         for(int i=0; i<5; i++) x.sum[i]=L.sum[i];
48         for(int i=0; i<5; i++) x.sum[(L.cnt+i)%5]+=R.sum[i];
49     }
50 
51     void update(int id, int pos, int val)
52     {
53         if(T[id].s==T[id].t)
54         {
55             for(int i=0; i<5; i++) T[id].sum[i]=0;
56             T[id].sum[1]=val;
57             if(val==0) T[id].cnt=0;
58             else T[id].cnt=1;
59             return;
60         }
61         int mid=(T[id].s+T[id].t)>>1;
62         if(pos<=mid) update(id<<1, pos, val);
63         else update(id<<1|1, pos, val);
64         pushUp(T[id], T[id<<1], T[id<<1|1]);
65     }
66 } tree;
67 
68 int main()
69 {
70     while(scanf("%d", &n)!=EOF)
71     {
72         haha.clear();
73         for(int i=0; i<n; i++)
74         {
75             scanf("%s", hehe);
76             op[i].fg=0, op[i].val=0;
77             if(strcmp(hehe, "sum")==0) continue;
78 
79             else if(strcmp(hehe, "add")==0) op[i].fg=1;
80             else op[i].fg=-1;
81             scanf("%d", &op[i].val);
82             haha.push_back(op[i].val);
83         }
84         sort(haha.begin(), haha.end());
85         ihash.clear();
86         int len=0;
87         for(vector<int>::iterator it=haha.begin(); it!=haha.end(); it++)
88             if(ihash.find(*it)==ihash.end())
89                 ihash.insert(make_pair(*it, ++len));
90         tree.build(1, 1, len);
91         for(int i=0; i<n; i++)
92         {
93             if(op[i].fg==1) tree.update(1, ihash[op[i].val], op[i].val);
94             else if(op[i].fg==-1) tree.update(1, ihash[op[i].val], 0);
95             else printf("%I64d\n", tree.T[1].sum[3]);
96         }
97     }
98     return 0;
99 }

题目链接 & AC通道

HDU 4288 Coder

原文地址:https://www.cnblogs.com/zhj5chengfeng/p/3043159.html