[CF]276E. Little Girl and Problem on Trees 树状数组

题目大意是说给一棵特殊的树,除了1之外所有点的度数<=2,每个点存有一个值,初值都是0

之后给出两种树上操作:

0:将到某个点v的距离<=d的所有点权值加上x

1:输出某点v的权值


第一眼看错题了,以为是修改一条链上的所有点的值,发现是水题,开始BIT搞……之后发现看错题了,不是给两点链操作而是按距离,果断删代码……

又看了几眼,发现确实是BIT……很不爽地隔了很长时间才重新搞这题……


直接粘代码……

/*
  把1号节点去掉就是一堆链,dfs找链染色确定下标,在链上的整体操作可以用BIT c维护
  把所有点放到一起,处理出来每个颜色的区间,问题就解决了一半……
  另一半是跨越1的问题,这里值只和深度有关
  处理出来每个点的深度dep[],那么超过1的再用另一个BIT c1存起来
  每个点的值就是c.get(pos[v])+c1.get(dep[v]) ?
  其实还有一个问题……
  假设对vv进行了修改,跨越了1,c1的更新是针对所有链,相当于vv所在链重复计算了……
  所以要在修改点所在链开始,长度为d-dep[vv]的一段减去x
  剩下的就是堆代码
*/
#include <iostream>
#include <cstring>
using namespace std;
#define N 200005
#define _int long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
struct BIT {
  _int n,c[N+1]; void init(int s) {n=s; memset(c,0,sizeof(c));}
  void change(int p, _int k) {for (; p<=n; p+=p&-p) c[p]+=k;}
  _int sum(int p) {_int s=0; for (; p; p-=p&-p) s+=c[p]; return s;}
};
struct BIT_ex {
  BIT t; void init(int s) {t.init(s);}
  void change(int l, int r, _int k) {t.change(l,k); t.change(r+1,-k);}
  _int get(int p) {return t.sum(p);}
};


struct {int p,next;} e[N];
BIT_ex c,c1;
int g[N],col[N],p[N],dep[N],st[N],ed[N],tot=0,len=0,ans1=0;
void addedge(int a,int b) {e[++tot].p=b; e[tot].next=g[a]; g[a]=tot;}
void dfs(int now,int pre,int coo,int dee) {
  col[now]=coo; p[now]=++len; dep[now]=dee;
  if (dee==1) st[coo]=len; bool last=true;
  for (int tmp=g[now]; tmp; tmp=e[tmp].next)
    if (e[tmp].p!=pre) {last=false; dfs(e[tmp].p,now,coo,dee+1);}
  if (last) ed[coo]=len;
}
int main() {
  int n,q; cin >> n >> q;
  memset(g,0,sizeof(g));
  for (int i=1; i<n; i++) {
    int u,v; cin >> u >> v;
    addedge(u,v); addedge(v,u);
  }
  for (int tmp=g[1],coo=1; tmp; tmp=e[tmp].next) {
    dfs(e[tmp].p,1,coo,1); coo++;
  }
  c.init(len); c1.init(len);
  while (q--) {
    int t,v; cin >> t >> v;
    if (t) {
      if (v==1) cout << ans1 << endl;
      else cout << c.get(p[v])+c1.get(dep[v]) << endl;
    } else {
      int x,d; cin >> x >> d;
      if (v==1) {c1.change(1,d,x); ans1+=x;}
      else {
        c.change(max(p[v]-d,st[col[v]]),min(p[v]+d,ed[col[v]]),x);
        if (d>=dep[v]) {
          ans1+=x; 
          if (d>dep[v]) {
            c1.change(1,d-dep[v],x);
            c.change(st[col[v]],min(st[col[v]]+d-dep[v]-1,ed[col[v]]),-x);
          }
        }
      }
    }        
  }
  //system("pause");
  return 0;
}


p.s.其实这个实现并不好……如果把每个链当成不同的BIT限定好起点终点来做,应该还能提高效率,懒人路过……


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值