Coder

Coder

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7069    Accepted Submission(s): 2635


Problem Description
  In mathematics and computer science, an algorithm describes a set of procedures or instructions that define a procedure. The term has become increasing popular since the advent of cheap and reliable computers. Many companies now employ a single coder to write an algorithm that will replace many other employees. An added benefit to the employer is that the coder will also become redundant once their work is done.  1
  You are now the signle coder, and have been assigned a new task writing code, since your boss would like to replace many other employees (and you when you become redundant once your task is complete).
Your code should be able to complete a task to replace these employees who do nothing all day but eating: make the digest sum.
  By saying “digest sum” we study some properties of data. For the sake of simplicity, our data is a set of integers. Your code should give response to following operations:
  1. add x – add the element x to the set;
  2. del x – remove the element x from the set;
  3. sum – find the digest sum of the set. The digest sum should be understood by

  where the set S is written as {a 1, a 2, ... , a k} satisfying a 1 < a 2 < a 3 < ... < a k 
  Can you complete this task (and be then fired)?
------------------------------------------------------------------------------
1 See http://uncyclopedia.wikia.com/wiki/Algorithm
 

 

Input
  There’re several test cases.
  In each test case, the first line contains one integer N ( 1 <= N <= 10 5 ), the number of operations to process.
  Then following is n lines, each one containing one of three operations: “add x” or “del x” or “sum”.
  You may assume that 1 <= x <= 10 9.
  Please see the sample for detailed format.
  For any “add x” it is guaranteed that x is not currently in the set just before this operation.
  For any “del x” it is guaranteed that x must currently be in the set just before this operation.
  Please process until EOF (End Of File).
 

 

Output
  For each operation “sum” please print one line containing exactly one integer denoting the digest sum of the current set. Print 0 if the set is empty.
 

 

Sample Input
9 add 1 add 2 add 3 add 4 add 5 sum add 6 del 3 sum 6 add 1 add 3 add 5 add 7 add 9 sum
 

 

Sample Output
3 4 5
Hint
C++ maybe run faster than G++ in this problem.
 题意:
有三种类型的操作,(1)."add x",表示往集合里添加数x。(2).“del x”表示将集合中数x删除。(3).“sum”求出从小到大排列的集合中下标模5为3的数的和。集合中的数都是唯一的
 
这里由于要进行插入和删除操作,肯定无法在线段树上进行在线操作,所以我们采用离线的方法。
先把所有的数据存在a数组里面,并把a数组的东西复制b数组里,对b数组进行离散化,根据b数组开始建树,在线段树维护两个值,num和s,num表示区间里元素的个数,s[i]代表区间里
所有满足下标x%5=i的元素和。
所以每次更新的时候,都是
                               t[rt].s[i] = t[rt<<1].s[i] + t[rt<<1|1].s[((i - t[rt<<1].num) % 5 + 5) % 5];
 

因为右结点的第x元素下标在父结点中应该对应的是第(x+左结点的元素个数)个元素(i为右边结点的下标),可以自己模拟下,就会了,即i=(x+cnt)%5,x=(5*n+i-cnt)%5,取模是为了防止负数

每次查询时只需要返回node[1].sum[2]即可

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 #define ll long long
 6 const int maxn = 1e5+7;
 7 char str[maxn][4];
 8 int a[maxn],b[maxn];
 9 struct node
10 {
11     int l, r;
12     ll s[10];
13     int num;
14 } t[maxn * 4];
15 void build(int rt, int l, int r)
16 {
17     t[rt].l = l;
18     t[rt].r = r;
19     memset(t[rt].s, 0, sizeof(t[rt].s));
20     if(l == r)
21     {
22         t[rt].num = 0;
23         return ;
24     }
25     int mid = (l + r) >> 1;
26     build(rt<<1, l, mid);
27     build(rt<<1|1, mid + 1, r);
28     t[rt].num = 0;
29    
30     memset(t[rt].s, 0, sizeof(t[rt].s));
31     
32 }
33 void update(int rt, int loc, int val, int op)
34 {
35     op == 1 ? t[rt].num ++ : t[rt].num--;
36     if(t[rt].l == t[rt].r)
37     {
38         t[rt].s[0] = op * val;
39         return ;
40     }
41     int mid = (t[rt].l + t[rt].r) >> 1;
42     if(loc <= mid)
43         update(rt<<1, loc, val, op);
44     else
45         update(rt<<1|1, loc, val, op);
46     for(int i = 0; i < 5; i++)
47     {
48         t[rt].s[i] = t[rt<<1].s[i] + t[rt<<1|1].s[((i - t[rt<<1].num) % 5 + 5) % 5];
49     }
50 }
51 
52 int main()
53 {
54 
55     int n;
56     while(~scanf("%d", &n))
57     {
58         int len = 0;
59        
60         for(int i = 0; i < n; i ++)
61         {
62             scanf("%s", str[i]);
63             if(str[i][0] != 's')
64             {
65                 scanf("%d", &a[i]);
66                 b[len ++] = a[i];
67             }
68         }
69         sort(b,b+len);
70         len = unique(b,b+len) - b;
71         build(1,1,len);
72         for(int i = 0; i < n; i ++)
73         {
74             if(str[i][0] == 'a')
75             {
76                 int x=lower_bound(b,b+len,a[i])-b+1;
77                 update(1, x, a[i], 1);
78             }
79             if(str[i][0] == 'd')
80             {
81                 int x=lower_bound(b,b+len,a[i])-b+1;
82                 update(1, x, a[i], 0);
83             }
84             if(str[i][0] == 's')
85             {
86                 printf("%I64d\n", t[1].s[2]);
87             }
88         }
89 
90 
91     }
92     return 0;
93 }

 

转载于:https://www.cnblogs.com/yuanlinghao/p/10849695.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值