fuzhou2082 树链剖分模板(边权,修改点查询区间和)

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include<stdio.h>
  3 #include<string.h>
  4 int now,cnt,d[50005][5];
  5 int next[100005],head[50005],point[100005];
  6 int son[50005],father[50005],num[50005],deep[50005];
  7 int pre[50005],tree[50005],top[50005];
  8 long long sumv[200005];
  9 void add(int x,int y,int w)
 10 {
 11     next[++now]=head[x];
 12     head[x]=now;
 13     point[now]=y;
 14 }
 15 void dfs1(int u)
 16 {
 17     num[u]=1;
 18     for (int i=head[u];i!=-1;i=next[i])
 19     {
 20         int v=point[i];
 21         if (v==father[u]) continue;
 22         father[v]=u; deep[v]=deep[u]+1;
 23         dfs1(v);
 24         num[u]+=num[v];
 25         if (son[u]==-1||num[son[u]]<num[v]) son[u]=v;
 26     }
 27 }
 28 void dfs2(int u,int lead)
 29 {
 30     top[u]=lead;
 31     tree[u]=++cnt;
 32     pre[cnt]=u;
 33     if (son[u]==-1) return;
 34     dfs2(son[u],lead);
 35     for (int i=head[u];i!=-1;i=next[i])
 36     {
 37         int v=point[i];
 38         if (son[u]!=v&&father[u]!=v) dfs2(v,v);
 39     }
 40 }
 41 void update(int o,int l,int r,int y,int dd)
 42 {
 43     if (y>r||y<l) return;
 44     if (l==r) { sumv[o]=dd; return; }
 45     else{
 46         int mid=l+(r-l)/2;
 47         if (y<=mid) update(o*2,l,mid,y,dd);
 48         if (y>mid) update(o*2+1,mid+1,r,y,dd);
 49         sumv[o]=sumv[o*2]+sumv[o*2+1];
 50     }
 51 }
 52 long long query(int o,int l,int r,int ql,int qr)
 53 {
 54     int mid=l+(r-l)/2;
 55     long long temp=0;
 56     if (ql<=l&&qr>=r) return sumv[o];
 57     if (ql<=mid) temp+=query(o*2,l,mid,ql,qr);
 58     if (qr>mid) temp+=query(o*2+1,mid+1,r,ql,qr);
 59     return temp;
 60 }
 61 long long change(int l,int r)
 62 {
 63     int temp;
 64     long long mm=0;
 65     while (top[l]!=top[r])
 66     {
 67         if (deep[top[l]]<deep[top[r]]) {temp=l; l=r; r=temp; }
 68         mm+=query(1,1,cnt,tree[top[l]],tree[l]);
 69         l=father[top[l]];
 70     }
 71     if (deep[l]>deep[r]) {temp=l; l=r; r=temp; }
 72     mm+=query(1,1,cnt,tree[son[l]],tree[r]);//边一定要注意这时改重链根的儿子所对应的父边
 73     return mm;
 74 }
 75 int main()
 76 {
 77     int n,m,i,temp,x,y,s;
 78     while (~scanf("%d%d",&n,&m))
 79     {
 80         memset(head,-1,sizeof(head));
 81         memset(son,-1,sizeof(son));
 82         deep[1]=0;  father[1]=1;
 83         now=cnt=0;
 84         for (i=1;i<n;i++)
 85         {
 86             scanf("%d%d%d",&d[i][0],&d[i][1],&d[i][2]);
 87             add(d[i][0],d[i][1],d[i][2]);
 88             add(d[i][1],d[i][0],d[i][1]);
 89         }
 90         dfs1(1); dfs2(1,1);
 91         memset(sumv,0,sizeof(sumv));
 92         for (i=1;i<n;i++)
 93         {
 94             if (deep[d[i][0]]>deep[d[i][1]]) {temp=d[i][0]; d[i][0]=d[i][1]; d[i][1]=temp; }
 95             update(1,1,cnt,tree[d[i][1]],d[i][2]);
 96         }
 97         for (i=1;i<=m;i++)
 98         {
 99             scanf("%d%d%d",&s,&x,&y);
100             if (s==1) printf("%I64d\n",change(x,y));
101             else update(1,1,cnt,tree[d[x][1]],y);
102         }
103     }
104     return 0;
105 }

http://acm.fzu.edu.cn/problem.php?pid=2082

posted on 2014-10-01 22:52  xiao_xin  阅读(144)  评论(0编辑  收藏  举报

导航