hdu 3333 线段树离线操作

来源:互联网 发布:js 数组中添加对象 编辑:程序博客网 时间:2024/05/11 01:14

这道题不同于一般普通的线段树,如果用在线算法的话会失败,以我的理解的话,是因为每个节点所要保存的信息都与前面位置的数据有关。不像通常的线段树,只与子节点的信息有关。

首先按照查询区间的右值进行排序。然后进行数据插入,把每个数放进线段树的时候,先判断再之前他有没有在线段树,如果在,则删除它,并把他的位置更新到当前点。

#include<stdio.h>  #include<string.h>  #include<algorithm>  #include<map>  using namespace std;  typedef __int64 ll;  #define N 300010  #define M 100010  struct   {      int l,r;      ll num;  }root[N*4];  struct Q  {      int s,t,ind;  }q[M];  bool cmp(Q i,Q j)  {      return i.t<j.t;  }  inline void build(int t,int x,int y)  {      root[t].l=x;      root[t].r=y;      root[t].num=0;      if(x==y) return;      int m=(x+y)>>1;      build(t*2,x,m);      build(t*2+1,m+1,y);  }  inline void Modefiy(int t,int x,ll val)  {      int l=root[t].l;      int r=root[t].r;      if(l==r)      {          root[t].num+=val;return;      }      int m=(l+r)>>1;      if(x<=m) Modefiy(t*2,x,val);      else Modefiy(t*2+1,x,val);      root[t].num=root[t*2].num+root[t*2+1].num;  }  inline ll query(int t,int x,int y)  {      int l=root[t].l;      int r=root[t].r;      if(l==x&&r==y)      {          return root[t].num;      }      int m=(l+r)>>1;      ll ans=0;      if(x<=m) ans+=query(t*2,x,min(m,y));      if(y>m) ans+=query(t*2+1,max(m+1,x),y);      return ans;  }    int t,n,qn;  ll a[N];  map<ll,int>m;  ll ans[M];  int main()  {      scanf("%d",&t);      while(t--)      {          m.clear();          scanf("%d",&n);          for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);          build(1,1,n);          scanf("%d",&qn);          for(int i=0;i<qn;i++)          {              scanf("%d%d",&q[i].s,&q[i].t);              q[i].ind=i;          }          sort(q,q+qn,cmp);          int k=1;          for(int i=0;i<qn;i++)          {              for(;k<=q[i].t;k++)              {                  if(m[a[k]]!=0) Modefiy(1,m[a[k]],-a[k]);                  m[a[k]]=k;                  Modefiy(1,k,a[k]);              }              ans[q[i].ind]=query(1,q[i].s,q[i].t);          }          for(int i=0;i<qn;i++) printf("%I64d\n",ans[i]);      }      return 0;  }  


0 0