• hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966

    题意:

    给出一棵树,并给定各个点权的值,然后有3种操作:

    I C1 C2 K: 把C1与C2的路径上的所有点权值加上K

    D C1 C2 K:把C1与C2的路径上的所有点权值减去K

    Q C:查询节点编号为C的权值

    分析:

    典型的树链剖分,对节点进行操作,可以用树状数组或者线段树。

    树链剖分+树状数组:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 
      6 using namespace std;
      7 const int maxn = 51000;
      8 
      9 struct Edge
     10 {
     11     int to,next;
     12 }edge[maxn*2];
     13 int head[maxn],cnt,num;
     14 int a[maxn],n,m,p,c[maxn];
     15 int size[maxn],top[maxn],id[maxn],fa[maxn],son[maxn],dep[maxn];
     16 
     17 void init()
     18 {
     19     memset(head,-1,sizeof(head));
     20     memset(son,-1,sizeof(son));
     21     memset(c,0,sizeof(c));
     22     cnt=0;
     23     num=0;
     24 }
     25 void addedge(int u,int v)
     26 {
     27     edge[cnt].to = v;
     28     edge[cnt].next = head[u];
     29        head[u] = cnt++;
     30 }
     31 
     32 void dfs_1(int u,int f,int d)
     33 {
     34     dep[u]=d;
     35     size[u]=1;
     36     fa[u]=f;
     37     for(int i=head[u];i!=-1;i=edge[i].next)
     38     {
     39         int v=edge[i].to;
     40         if(v==f)
     41             continue;
     42         dfs_1(v,u,d+1);
     43         size[u]+=size[v];
     44         if(son[u]==-1||size[son[u]]<size[v])
     45             son[u]=v;
     46     }
     47 }
     48 
     49 void dfs_2(int u,int tp)
     50 {
     51     top[u] = tp;
     52     id[u] = ++num;
     53     if(son[u]!=-1)
     54         dfs_2(son[u],tp);
     55     for(int i=head[u];i!=-1;i=edge[i].next)
     56     {
     57         int v=edge[i].to;
     58         if(v==fa[u]||v==son[u])
     59             continue;
     60         dfs_2(v,v);
     61     }
     62 }
     63 
     64 int lowbit(int x)
     65 {
     66     return x&-x;
     67 }
     68 
     69 int sum(int x)
     70 {
     71     int res=0;
     72     while(x>0)
     73     {
     74         res+=c[x];
     75         x-=lowbit(x);
     76     }
     77     return res;
     78 }
     79 
     80 void add(int x,int d)
     81 {
     82     while(x<=n)
     83     {
     84         c[x]+=d;
     85         x+=lowbit(x);
     86     }
     87 }
     88 
     89 void change(int u,int v,int val)
     90 {
     91     int tp1=top[u],tp2=top[v];
     92     while(tp1!=tp2)
     93     {
     94         if(dep[tp1]<dep[tp2])
     95         {
     96             swap(tp1,tp2);
     97             swap(u,v);
     98         }
     99         add(id[tp1],val);
    100         add(id[u]+1,-val);
    101         u=fa[tp1];
    102         tp1=top[u];
    103     }
    104     if(dep[u]>dep[v])
    105         swap(u,v);
    106     add(id[u],val);
    107     add(id[v]+1,-val);
    108 }
    109 
    110 int main()
    111 {
    112     while(~scanf("%d%d%d",&n,&m,&p))
    113     {
    114         init();
    115         for(int i=1;i<=n;i++)
    116             scanf("%d",&a[i]);
    117         for(int i=1;i<=m;i++)
    118         {
    119             int u,v;
    120             scanf("%d%d",&u,&v);
    121             addedge(u,v);
    122             addedge(v,u);
    123         }
    124         dfs_1(1,0,1);
    125         dfs_2(1,1);
    126         for(int i=1;i<=n;i++)
    127         {
    128             add(id[i],a[i]);
    129             add(id[i]+1,-a[i]);
    130         }
    131         char s[5];
    132         int c1,c2,k,c;
    133         for(int i=0;i<p;i++)
    134         {
    135             scanf("%s",s);
    136             if(s[0]=='I')
    137             {
    138                 scanf("%d%d%d",&c1,&c2,&k);
    139                 change(c1,c2,k);
    140             }
    141             if(s[0]=='D')
    142             {
    143                 scanf("%d%d%d",&c1,&c2,&k);
    144                 change(c1,c2,-k);
    145             }
    146             if(s[0]=='Q')
    147             {
    148                 scanf("%d",&c);
    149                 cout<<sum(id[c])<<endl;
    150             }
    151         }
    152     }
    153     return 0;
    154 }

    树链剖分+线段树:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 using namespace std;
      6 const int maxn = 51000;
      7 int n,m,p;
      8 int val[maxn],a[maxn];
      9 struct Edge
     10 {
     11     int to,next;
     12 }edge[maxn*2];
     13 int head[maxn],add[maxn*4];
     14 int dep[maxn],fa[maxn],size[maxn],son[maxn],top[maxn],id[maxn];
     15 int cnt,num;
     16 void init()
     17 {
     18         memset(head,-1,sizeof(head));
     19     memset(son,-1,sizeof(son));
     20     memset(add,0,sizeof(add));
     21     cnt=0;
     22         num=0;
     23 }
     24 
     25 void addedge(int u,int v)
     26 {
     27     edge[cnt].to=v;
     28     edge[cnt].next=head[u];
     29     head[u]=cnt++;
     30 }
     31 
     32 void dfs_1(int u,int f,int d)
     33 {
     34     dep[u]=d;
     35     size[u]=1;
     36     fa[u]=f;
     37     for(int i=head[u];i!=-1;i=edge[i].next)
     38     {
     39         int v=edge[i].to;
     40         if(v==f)
     41             continue;
     42         dfs_1(v,u,d+1);
     43         size[u]+=size[v];
     44         if(son[u]==-1||size[son[u]]<size[v])
     45             son[u]=v;
     46     }
     47 }
     48 
     49 void dfs_2(int u,int tp)
     50 {
     51     top[u] = tp;
     52     id[u] = ++num;
     53     if(son[u]!=-1) 
     54         dfs_2(son[u],tp);
     55     for(int i=head[u];i!=-1;i=edge[i].next)
     56     {
     57         int v = edge[i].to;
     58         if(v == fa[u] ||v == son[u])
     59             continue;
     60         dfs_2(v,v);
     61     }
     62 }
     63 
     64 struct Tree
     65 {
     66     int left,right;
     67     int sum;
     68 }tree[maxn*4];
     69 
     70 void pushup(int i)
     71 {
     72     tree[i].sum = tree[i*2].sum + tree[i*2+1].sum;
     73 }
     74 
     75 void build(int i,int begin,int end)
     76 {
     77     tree[i].left=begin;
     78     tree[i].right=end;
     79     if(begin==end)
     80     {
     81         tree[i].sum=val[begin];
     82         return;
     83     }
     84     int mid=(begin+end)/2;
     85     build(i*2,begin,mid);
     86     build(i*2+1,mid+1,end);
     87     pushup(i);
     88 }
     89 
     90 void pushdown(int i)
     91 {
     92     if(add[i])
     93     {
     94         add[i*2] += add[i];
     95         add[i*2+1] += add[i];
     96         int mid=(tree[i].left+tree[i].right)/2;
     97         tree[i*2].sum += add[i]*(mid-tree[i].left+1);
     98         tree[i*2+1].sum += add[i]*(tree[i].right-mid);
     99         add[i]=0;
    100     }
    101 }
    102 
    103 void update(int i,int begin,int end,int value)
    104 {
    105     if(tree[i].left>=begin&&tree[i].right<=end)
    106     {
    107         add[i]+=value;
    108         tree[i].sum+=value*(tree[i].right-tree[i].left+1);
    109         return;
    110     }
    111     pushdown(i);
    112     int mid=(tree[i].left+tree[i].right)/2;
    113     if(mid>=begin)
    114         update(i*2,begin,end,value);
    115     if(mid<end)
    116         update(i*2+1,begin,end,value);
    117     pushup(i);
    118 }
    119 
    120 void change(int u,int v,int value)
    121 {
    122     int tp1=top[u],tp2=top[v];
    123     while(tp1!=tp2)
    124     {
    125         if(dep[tp1]<dep[tp2])
    126         {
    127             swap(tp1,tp2);
    128             swap(u,v);
    129         }
    130         update(1,id[tp1],id[u],value);
    131         u = fa[tp1];
    132         tp1 = top[u];
    133     }
    134     if(dep[u]>dep[v])
    135         swap(u,v);
    136     update(1,id[u],id[v],value);
    137 }
    138 
    139 long long query(int i,int begin,int end)
    140 {
    141     if(tree[i].left>=begin&&tree[i].right<=end)
    142         return tree[i].sum;
    143     pushdown(i);
    144     int mid=(tree[i].left+tree[i].right)/2;
    145     long long ans=0;
    146     if(mid>=begin)
    147         ans+=query(i*2,begin,end);
    148     if(mid<end)
    149         ans+=query(i*2+1,begin,end);
    150     return ans;
    151 }
    152 
    153 int main()
    154 {
    155     while(~scanf("%d%d%d",&n,&m,&p))
    156     {
    157         init();
    158         for(int i=1;i<=n;i++)
    159             scanf("%d",&a[i]);
    160         for(int i=1;i<=m;i++)
    161         {
    162             int u,v;
    163             scanf("%d%d",&u,&v);
    164             addedge(u,v);
    165             addedge(v,u);
    166         }
    167         dfs_1(1,0,1);
    168         dfs_2(1,1);
    169 
    170         for(int i=1;i<=n;i++)
    171             val[id[i]]=a[i];
    172         build(1,1,n);
    173         char s[5];
    174         int c1,c2,k,c;
    175         for(int i=0;i<p;i++)
    176         {
    177             scanf("%s",s);
    178             if(s[0]=='I')
    179             {
    180                 scanf("%d%d%d",&c1,&c2,&k);
    181                 change(c1,c2,k);
    182             }
    183             if(s[0]=='D')
    184             {
    185                 scanf("%d%d%d",&c1,&c2,&k);
    186                 change(c1,c2,-k);
    187             }
    188             if(s[0]=='Q')
    189             {
    190                 scanf("%d",&c);
    191                 cout<<query(1,id[c],id[c])<<endl;
    192             }
    193         }
    194     }
    195     return 0;
    196 }
  • 相关阅读:
    20191323王予涵第五章学习笔记
    反汇编测试
    20191323王予涵第四章学习笔记
    20191323王予涵2.3.1测试
    鲲鹏服务器测试
    缓冲区溢出攻击实验
    20191323王予涵第三章学习笔记
    20191323王予涵第十一章学习笔记
    20191323王予涵第七、八章学习笔记
    20191323王予涵sort
  • 原文地址:https://www.cnblogs.com/yaoyueduzhen/p/5311116.html
Copyright © 2020-2023  润新知