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;
}
View Code

 

--------------oshixiaoxiliu

posted @ 2013-08-28 13:26  oucacm  阅读(124)  评论(0)    收藏  举报