CodeForces 276E - Little Girl and Problem on Trees 区间更新..N+1个线段树

来源:互联网 发布:hbo直播软件 编辑:程序博客网 时间:2024/04/19 13:48

    注意题目设定..除了根节点1外...其他的点至多两个度..而每个非点必须要有一个父亲..所以每个非根节点至多一个孩子..说明题目所给的树一定是这样的:


   对于一个点的上下范围更新...有两种情况发生...一个是在所在的线段内更新...一个是上界超过了线段...更新到其他的线段上去...

   对于N个线段..可以用N个线段树来维护其区间更新...但是对于跨过1点更新到其他线段的情况..若每次一条一条的更新..绝对超市..这是用一颗特殊的线段树来维护从1出发到多深..加了多少的值...

   为了能方便的维护这颗特别的线段树...当其他的线段会更新到点1时...要做更新范围的调整..比如:


  要在2号点更新距离为3的..那么更新范围是红色标出的部分...把这个部分分解为为黄色和红色的部分分别处理..红色就是在这个线段是做区间更新..黄色是在点1记录的距离上区间更新... 

  由于N+1颗线段树的长度是未知的..所以用vector来开...因为vector是动态申请空间的..并且可以通过下标直接访问元素...


Program:

#include<iostream>#include<stack>#include<queue>#include<stdio.h>#include<algorithm>#include<string.h>#include<cmath>#define ll long long#define oo 1000000007#define MAXN 100004using namespace std;  struct node{       int Tn,g; }P[MAXN];vector<int> T[MAXN],col[MAXN],t0;  int n,num,M[MAXN];void dfs(int x,int m,int f,int t){      P[x].Tn=m,P[x].g=t;      col[num].push_back(0);      for (int i=0;i<T[x].size();i++)        if (T[x][i]!=f)           dfs(T[x][i],m,x,t+1);      if (t>M[0]) M[0]=t;      return;}void PushDown(int M,int len,int now){      if (!col[M][now]) return;       col[M][now<<1]+=col[M][now];      col[M][(now<<1)|1]+=col[M][now];       col[M][now]=0;      return;}void update(int M,int L,int R,int c,int l,int r,int now) // M用于确定是哪颗树{      if (L<=l && R>=r)      {               col[M][now]+=c;              return;      }      PushDown(M,r-l+1,now);      int mid=(l+r)>>1;      if (L<=mid) update(M,L,R,c,l,mid,now<<1);      if (R>mid)  update(M,L,R,c,mid+1,r,(now<<1)|1);      return;      }int query(int M,int p,int l,int r,int now)   {      if (l==r) return col[M][now];      PushDown(M,r-l+1,now);      int mid=(l+r)>>1;      if (p<=mid) return query(M,p,l,mid,now<<1);      if (p>mid)  return query(M,p,mid+1,r,(now<<1)|1); }int main(){        int i,q;       scanf("%d%d",&n,&q);      for (i=1;i<=n;i++) T[i].clear();      for (i=1;i<n;i++)      {            int x,y;            scanf("%d%d",&x,&y);            T[x].push_back(y),T[y].push_back(x);      }      num=0,P[1].g=0,M[0]=0;      for (i=0;i<T[1].size();i++)      {             col[++num].clear(),col[num].push_back(0);            dfs(T[1][i],num,1,1);       }       col[0].clear(); i=M[0]<<2;      while (i--) col[0].push_back(0);      for (i=1;i<=num;i++)      {            int x=col[i].size();            M[i]=x-1,x<<=2;            col[i].clear();             while (x--) col[i].push_back(0);      }      while (q--)      {            int tp,v,x,d;            scanf("%d",&tp);            if (!tp)            {                    int l,r,p,t;                    scanf("%d%d%d",&v,&x,&d);                    if (P[v].g-d<=0) l=d-P[v].g+1,update(0,0,min(M[0],l-1),x,0,M[0],1);                        else l=P[v].g-d;                    if (v==1) continue;                    r=min(M[P[v].Tn],P[v].g+d);                    if (r<l) continue;                    update(P[v].Tn,l,r,x,1,M[P[v].Tn],1);             }else            {                    int ans=0;                    scanf("%d",&v);                     ans=query(0,P[v].g,0,M[0],1);                    if (v!=1) ans+=query(P[v].Tn,P[v].g,1,M[P[v].Tn],1);                    printf("%d\n",ans);            }      }      return 0;}


原创粉丝点击