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 }

 

posted @ 2016-03-23 14:54  邀月独斟  阅读(159)  评论(0编辑  收藏  举报