hdu4288 Coder(线段树单点更新)

题意:支持增删,查操作,最后的序列式递增的。

做法:主要是如何维护mod5的sum值,这里左儿子可以不用管,关键是右儿子的处理,可以假设右儿子有t个节点,左儿子有cnt个节点,

则令(t+cnt)MOD 5= i 则tmod5=(i-cnt MOD 5)MOD 5 ,所以剩下的就是维护每个节点的节点总数以及相应的和就好了。

  1 #include<cstring>

 2 #include<algorithm>
 3 #include<cstdio>
 4 typedef  long  long ll;
 5  using  namespace std;
 6  #define lz u<<1,l,mid
 7  #define rz u<<1|1,mid+1,r
 8  const  int MAX =  100000+ 10;
 9  struct node
10 {
11     ll sum[ 6],cnt;
12 }tree[MAX<< 2];
13  int num[MAX],rnum[MAX],check[MAX];
14  void build( int u, int l, int r)
15 {
16      for( int i= 0;i< 5;i++) tree[u].sum[i]= 0;
17     tree[u].cnt= 0;
18      if(l!=r)
19     {
20          int mid=(l+r)>> 1;
21         build(lz); build(rz);
22     }
23 }
24  void add( int u, int l, int r, int x, int d, int cur)
25 {
26      if(l==r)
27     {
28         tree[u].sum[ 1]+=d;
29         tree[u].cnt+=cur;
30          return;
31     }
32      int mid=(l+r)>> 1;
33      if(x<=mid) add(lz,x,d,cur);
34      else add(rz,x,d,cur);
35     tree[u].cnt=tree[u<< 1].cnt+tree[u<< 1| 1].cnt;
36      for( int i= 0;i< 5;i++)
37     {
38         tree[u].sum[i]=tree[u<< 1].sum[i]+tree[u<< 1| 1].sum[((i-tree[u<< 1].cnt)% 5+ 5)% 5];
39     }
40 }
41  int main()
42 {
43      int n,a;  char str[ 10];
44      while(scanf( " %d ",&n)== 1)
45     {
46          int cur= 0;
47          for( int i= 0;i<n;i++)
48         {
49             scanf( " %s ",str);
50              if(str[ 0]== ' a ')
51             {
52                 check[i]= 1;
53                 scanf( " %d ",&a);
54                 num[i]=rnum[cur++]=a;
55             }
56              else  if(str[ 0]== ' d ')
57             {
58                 check[i]= 2;
59                 scanf( " %d ",&num[i]);
60             }
61              else  check[i]= 3;
62         }
63         sort(rnum,rnum+cur);
64          int tot=unique(rnum,rnum+cur)-rnum;
65          if(tot!= 0) build( 1, 1,tot);
66          for( int i= 0;i<n;i++)
67         {
68              if(check[i]== 1)
69             {
70                  int pos=lower_bound(rnum,rnum+tot,num[i])-rnum+ 1;
71                 add( 1, 1,tot,pos,num[i], 1);
72             }
73              else  if(check[i]== 2)
74             {
75                  int pos=lower_bound(rnum,rnum+tot,num[i])-rnum + 1;
76                 add( 1, 1,tot,pos,-num[i],- 1);
77             }
78              else
79             {
80                  if(tot== 0) printf( " 0\n ");
81                  else
82                 {
83                     printf( " %I64d\n ",tree[ 1].sum[ 3]);
84                 }
85             }
86         }
87     }
88      return  0;
89 }

转载于:https://www.cnblogs.com/acvc/p/3537395.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值