树链剖分+线段树 HDU3966 权值在点 模板

来源:互联网 发布:程序员改bug 编辑:程序博客网 时间:2024/06/06 02:07

树链剖分模板题。

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<vector>#include<algorithm>#include<iostream>using namespace std;#define maxn 50010int n,m,Q;int tim;//时间戳int a[maxn];//树上每个节点的初始值int siz[maxn];//siz[u]表示以u为根的子树的节点数int top[maxn];//树链上深度最小的点int son[maxn];//重儿子int dep[maxn];//深度int tid[maxn];//节点的时间戳int tid1[maxn];//tid[i]=j表示时间戳为i的节点是jint fa[maxn];//父节点bool vis[maxn];vector<int>edge[maxn];void init(int n){     for(int i=1;i<=n;i++)     {          siz[i]=top[i]=son[i]=0;          dep[i]=tid[i]=tid1[i]=fa[i]=0;          vis[i]=false;          tim=0;          edge[i].clear();     }}void add(int x,int y) //无向图加双向边{     edge[x].push_back(y);     edge[y].push_back(x);}//树链剖分void dfs1(int u,int pre){     vis[u]=true;     siz[u]=1;     fa[u]=pre;     dep[u]=dep[pre]+1;//注意根节点比较特殊     int l=edge[u].size();     for(int i=0;i<l;i++)     {          int v=edge[u][i];          if(v!=fa[u]&&vis[v]==false)          {               dfs1(v,u);               siz[u]+=siz[v];               if(son[u]==0)                    son[u]=v;               else if(siz[son[u]]<siz[v])                    son[u]=v;          }     }}void dfs2(int u,int tp)//tp表示节点u的顶部;{     vis[u]=true;     tid[u]=++tim;     tid1[tim]=u;     top[u]=tp;     if(son[u]!=0)     {          dfs2(son[u],tp);//同一条重链的顶部相同     }     int l=edge[u].size();     for(int i=0;i<l;i++)     {          int v=edge[u][i];          if(v!=fa[u]&&v!=son[u]&&vis[v]==false)//注意去掉重儿子          {               dfs2(v,v);          }     }}void update(int i,int l,int r,int v);//线段树更新函数void change(int x,int y,int val){     while(top[x]!=top[y])     {          if(dep[top[x]]<dep[top[y]])               swap(x,y);          update(1,tid[top[x]],tid[x],val);//dfs2时顶部先访问,故tid[top]较小          x=fa[top[x]];//因为top[x]->x路径上的所有点已经被更新了     }     if(dep[x]>dep[y])//同一条重链上深度小的tid小          swap(x,y);     update(1,tid[x],tid[y],val);}//线段树部分struct node{     int l,r,val,lazy;}q[maxn*4];void build(int i,int l,int r){     q[i].l=l;     q[i].r=r;     q[i].lazy=q[i].val=0;     if(l==r)     {          q[i].val=a[tid1[l]];          return;     }     int mid=(l+r)/2;     build(i*2,l,mid);     build(i*2+1,mid+1,r);}void pushdown(int i){     if(q[i].lazy!=0)     {          q[i*2].val+=q[i].lazy;          q[i*2+1].val+=q[i].lazy;          q[i*2].lazy+=q[i].lazy;          q[i*2+1].lazy+=q[i].lazy;          q[i].lazy=0;     }}void update(int i,int l,int r,int v){     if(q[i].l==l&&q[i].r==r)     {          q[i].val+=v;          q[i].lazy+=v;          return;     }     pushdown(i);     int mid=(q[i].l+q[i].r)/2;     if(r<=mid)          update(i*2,l,r,v);     else if(l>mid)          update(i*2+1,l,r,v);     else     {          update(i*2,l,mid,v);          update(i*2+1,mid+1,r,v);     }}int query(int i,int x){     if(q[i].l==x&&q[i].r==x)     {          return q[i].val;     }     pushdown(i);     int mid=(q[i].l+q[i].r)/2;     if(x<=mid)          return query(i*2,x);     else          return query(i*2+1,x);}int main(void){     int i,j,k,x,y,z;     char op[2];     while(scanf("%d%d%d",&n,&m,&Q)!=EOF)     {          init(n);          for(i=1;i<=n;i++)               scanf("%d",&a[i]);          for(i=1;i<=m;i++)          {               scanf("%d%d",&x,&y);               add(x,y);          }          dfs1(1,0);          memset(vis,false,sizeof(vis));          dfs2(1,1);          build(1,1,n);          while(Q--)          {               scanf("%s",op);               if(op[0]=='Q')               {                    scanf("%d",&x);                    printf("%d\n",query(1,tid[x]));               }               else               {                    scanf("%d%d%d",&x,&y,&z);                    if(op[0]=='I')                         change(x,y,z);                    else                         change(x,y,-z);               }          }     }     return 0;}