日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hdu3966-线段树

發布時間:2023/12/18 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu3966-线段树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

Description
Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, the enemy has N camps out of his kingdom and M edges connect them. It is guaranteed that for any two camps, there is one and only one path connect them. At first Aragorn know the number of enemies in every camp. But the enemy is cunning , they will increase or decrease the number of soldiers in camps. Every time the enemy change the number of soldiers, they will set two camps C1 and C2. Then, for C1, C2 and all camps on the path from C1 to C2, they will increase or decrease K soldiers to these camps. Now Aragorn wants to know the number of soldiers in some particular camps real-time.

Input

Multiple test cases, process to the end of input.
For each case, The first line contains three integers N, M, P which means there will be N(1 ≤ N ≤ 50000) camps, M(M = N-1) edges and P(1 ≤ P ≤ 100000) operations. The number of camps starts from 1.
The next line contains N integers A1, A2, …AN(0 ≤ Ai ≤ 1000), means at first in camp-i has Ai enemies.
The next M lines contains two integers u and v for each, denotes that there is an edge connects camp-u and camp-v.
The next P lines will start with a capital letter ‘I’, ‘D’ or ‘Q’ for each line.
‘I’, followed by three integers C1, C2 and K( 0≤K≤1000), which means for camp C1, C2 and all camps on the path from C1 to C2, increase K soldiers to these camps.
‘D’, followed by three integers C1, C2 and K( 0≤K≤1000), which means for camp C1, C2 and all camps on the path from C1 to C2, decrease K soldiers to these camps.
‘Q’, followed by one integer C, which is a query and means Aragorn wants to know the number of enemies in camp C at that time.

Output
For each query, you need to output the actually number of enemies in the specified camp.

Sample Input
3 2 5
1 2 3
2 1
2 3
I 1 3 5
Q 2
D 1 2 2
Q 1
Q 3

Sample Output
7
4
8

題意
有n個營地,被m條路連接,p次詢問,每次詢問有三種情況:
I C1 C2 K,讓C1營地到C2營地之間所有營地增加K個人
D C1 C2 K ,讓C1營地到C2營地之間所有營地減少K個人
Q C 詢問C營地當前人數

思路
第一道樹鏈剖分感覺還蠻好的,開7個數組作用如下:siz保存以i為根的子樹節點個數,top保存i節點所在鏈的頂端節點,son保存i節點的重兒子,fa保存i節點的父親節點,dep保存i節點的深度(根為1),,tid保存i節點dfs后的新編號,rak保存新編號i對應的節點(rak[i]=j,tid[j]=i)。

第一次dfs可以得到siz,son,fat,dep四個數組,第二次可以得到tid,rak,top三個數組,這時如果我們要更新(x,y)營地,可以通過類似LCA倍增的做法,每次更新深度較低的點到該點的top點之間的數據,依次更新。用線段樹完成更新操作,樹鏈剖分更多的是讓樹上兩個點可以通過類似LCA的方式找到路徑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstdlib>
#include<map>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<set>
#define lson l,mid,i<<1
#define rson mid+1,r,i<<1|1
using namespace std;
typedef long long ll;
const int maxn = 51000;
struct node {
int s, e, next;
}edge[maxn * 2];
int n, m, p;
int son[maxn], top[maxn], tid[maxn], fat[maxn], siz[maxn], dep[maxn], rak[maxn];
int head[maxn], len, dfx;
//siz保存以i為根的子樹節點個數,top保存i節點所在鏈的頂端節點,son保存i節點的重兒子,fa保存i節點的父親節點\
dep保存i節點的深度(根為1),,tid保存i節點dfs后的新編號,rk保存新編號i對應的節點(rak[i]=j,tid[j]=i)。
void dfs1(int x, int fa, int d) {
siz[x] = 1, dep[x] = d;
fat[x] = fa;
son[x] = -1;
for (int i = head[x]; i != -1; i = edge[i].next) {
int y = edge[i].e;
if (y == fa)
continue;
dfs1(y, x, d + 1);
siz[x] += siz[y];
if (son[x] == -1 || siz[y] > siz[son[x]])
son[x] = y;
}
}
void dfs2(int x, int c) {
top[x] = c;
tid[x] = ++dfx;
rak[dfx] = x;
if (son[x]==-1)
return;
dfs2(son[x], c);
for (int i = head[x]; i != -1; i = edge[i].next) {
int y = edge[i].e;
if (y == fat[x] || y == son[x])
continue;
dfs2(y, y);
}
}
void add(int s, int e) {
edge[len].e = e;
edge[len].next = head[s];
head[s] = len++;
}
void init() {
memset(head, -1, sizeof(head));
len = 0;
dfx = 0;
}
ll sum[maxn * 4];
ll lazy[maxn * 4];
ll a[maxn * 4];
void up(int i) {
sum[i] = sum[i << 1] + sum[i << 1 | 1];
}
void down(int i, int len) {
if (lazy[i]) {
lazy[i << 1] += lazy[i];
lazy[i << 1 | 1] += lazy[i];
sum[i << 1] += lazy[i] * (len - (len >> 1));
sum[i << 1 | 1] += lazy[i] * (len >> 1);
lazy[i] = 0;
}
}
void build(int l, int r, int i) {
lazy[i] = 0;
if (l == r) {
sum[i] = a[rak[l]];
return;
}
int mid = (l + r) / 2;
build(lson);
build(rson);
up(i);
}
void update(int L, int R, int k, int l, int r, int i) {
if (L <= l && r <= R) {
sum[i] += (r - l + 1)*k;
lazy[i] += k;
return;
}
down(i, r - l + 1);
int mid = (l + r) / 2;
if (L <= mid)
update(L, R, k, lson);
if (R > mid)
update(L, R, k, rson);
up(i);
}
ll query(int k, int l, int r, int i) {
if (l == r) {
return sum[i];
}
down(i, r - l + 1);
int mid = (l + r) / 2;
int ans = 0;
if (k <= mid)
ans += query(k, lson);
else
ans += query(k, rson);
return ans;

}
void setupdate(int x, int y, int k) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]])
swap(x, y);
update(tid[top[x]], tid[x], k, 1, n, 1);
x = fat[top[x]];
}
if (dep[x] < dep[y])
swap(x, y);
update(tid[y], tid[x], k, 1, n, 1);
}
int main() {
while (scanf("%d%d%d", &n, &m, &p) != EOF) {
init();
int x, y, z;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) {
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
dfs1(1, 0, 0);
dfs2(1, 1);
build(1, n, 1);
while (p--) {
char s[2];
scanf("%s", s);
if (s[0] == 'Q') {
scanf("%d", &x);
printf("%d\n", query(tid[x], 1, n, 1));
}
else {
scanf("%d%d%d", &x, &y, &z);
if (s[0] == 'D')
z = -z;
setupdate(x, y, z);
}
}
}
}

謝謝你請我吃糖果

總結

以上是生活随笔為你收集整理的hdu3966-线段树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。