热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

洛谷P4175网络管理

题意:链上带修第k大。这毒瘤题。。。别看题意只有7个字,能把我吊打死。。。介绍其中两种做法好了。其实思想上是一样的。对于每一个点,建立权值

题意:链上带修第k大。

这毒瘤题。。。别看题意只有7个字,能把我吊打死。。。

介绍其中两种做法好了。其实思想上是一样的。

对于每一个点,建立权值线段树,维护它到根路径上的所有权值。

一条路径上的点集就是x + y - z - fa z,此处z是lca x y

这样查询就可以轻易做到了。怎么建出来呢?

考虑每个点都要在它的子树中插入。那么我们搞出DFS序来,子树就是上面的一段区间。

我们就要对于这个DFS序,支持区间加(插入),单点求值。很容易想到树状数组+差分。

那么我们就用树状数组维护差分后的值域线段树,这样就是单点修改和区间求和了。

也就是树状数组套线段树...

具体实现上,查询操作有点小技巧。因为要同时查4个位置然后加加减减,每个位置又会涉及查询log棵线段树,所以就用一个now i来维护i版本的线段树当前走到的节点,用一个栈来存要用到的线段树以便更新。

然后修改操作嘛,就是删除之前的再加上新的。

时间复杂度nlog2n。

1 #include
2 #include
3
4 const int N = 100010, lm = 1e8, M = 22000010;
5
6 struct Edge {
7 int nex, v;
8 }edge[N <<1]; int top;
9
10 int e[N], p[N], num, val[N], pos[N], n, ed[N], fa[N][20], tot, pw[N], d[N], rt[N], now[N], tp;
11 int sum[M], ls[M], rs[M];
12 bool vis[N];
13
14 inline void add(int x, int y) {
15 top&#43;&#43;;
16 edge[top].v &#61; y;
17 edge[top].nex &#61; e[x];
18 e[x] &#61; top;
19 return;
20 }
21
22 void DFS(int x, int f) {
23 fa[x][0] &#61; f;
24 d[x] &#61; d[f] &#43; 1;
25 pos[x] &#61; &#43;&#43;num;
26 for(int i &#61; e[x]; i; i &#61; edge[i].nex) {
27 int y &#61; edge[i].v;
28 if(y !&#61; f) {
29 DFS(y, x);
30 }
31 }
32 ed[x] &#61; num;
33 return;
34 }
35
36 void Add(int p, int v, int l, int r, int &o) {
37 if(!o) {
38 o &#61; &#43;&#43;tot;
39 }
40 if(l &#61;&#61; r) {
41 sum[o] &#43;&#61; v;
42 return;
43 }
44 int mid &#61; (l &#43; r) >> 1;
45 if(p <&#61; mid) {
46 Add(p, v, l, mid, ls[o]);
47 }
48 else {
49 Add(p, v, mid &#43; 1, r, rs[o]);
50 }
51 sum[o] &#61; sum[ls[o]] &#43; sum[rs[o]];
52 return;
53 }
54
55 inline void insert(int id, int p, int v) {
56 for(int i &#61; id; i <&#61; num; i &#43;&#61; (i & (-i))) {
57 Add(p, v, 1, lm, rt[i]);
58 }
59 return;
60 }
61
62 inline int lca(int x, int y) {
63 if(d[x] > d[y]) {
64 std::swap(x, y);
65 }
66 int t &#61; pw[n];
67 while(t >&#61; 0 && d[y] > d[x]) {
68 if(d[fa[y][t]] >&#61; d[x]) {
69 y &#61; fa[y][t];
70 }
71 t--;
72 }
73 if(x &#61;&#61; y) {
74 return x;
75 }
76 t &#61; pw[n];
77 while(t >&#61; 0 && fa[x][0] !&#61; fa[y][0]) {
78 if(fa[x][t] !&#61; fa[y][t]) {
79 x &#61; fa[x][t];
80 y &#61; fa[y][t];
81 }
82 t--;
83 }
84 return fa[x][0];
85 }
86
87 inline int ask(int k, int x, int y) {
88 int z &#61; lca(x, y);
89 if(d[x] &#43; d[y] - 2 * d[z] &#43; 1 < k) {
90 return -1;
91 }
92 // x &#43; y - z - fa[z]
93 int w &#61; fa[z][0];
94 x &#61; pos[x], y &#61; pos[y], z &#61; pos[z], w &#61; pos[w];
95 for(int i &#61; x; i >&#61; 1; i -&#61; (i & (-i))) {
96 if(!vis[i]) {
97 vis[i] &#61; 1;
98 p[&#43;&#43;tp] &#61; i;
99 now[i] &#61; rt[i];
100 }
101 }
102 for(int i &#61; y; i >&#61; 1; i -&#61; (i & (-i))) {
103 if(!vis[i]) {
104 vis[i] &#61; 1;
105 p[&#43;&#43;tp] &#61; i;
106 now[i] &#61; rt[i];
107 }
108 }
109 for(int i &#61; z; i >&#61; 1; i -&#61; (i & (-i))) {
110 if(!vis[i]) {
111 vis[i] &#61; 1;
112 p[&#43;&#43;tp] &#61; i;
113 now[i] &#61; rt[i];
114 }
115 }
116 for(int i &#61; w; i >&#61; 1; i -&#61; (i & (-i))) {
117 if(!vis[i]) {
118 vis[i] &#61; 1;
119 p[&#43;&#43;tp] &#61; i;
120 now[i] &#61; rt[i];
121 }
122 }
123 //
124 int l &#61; 1, r &#61; lm;
125 while(l < r) {
126 int mid &#61; (l &#43; r) >> 1, s &#61; 0;
127 for(int i &#61; x; i >&#61; 1; i -&#61; i & (-i)) {
128 s &#43;&#61; sum[rs[now[i]]];
129 }
130 for(int i &#61; y; i >&#61; 1; i -&#61; i & (-i)) {
131 s &#43;&#61; sum[rs[now[i]]];
132 }
133 for(int i &#61; z; i >&#61; 1; i -&#61; i & (-i)) {
134 s -&#61; sum[rs[now[i]]];
135 }
136 for(int i &#61; w; i >&#61; 1; i -&#61; i & (-i)) {
137 s -&#61; sum[rs[now[i]]];
138 }
139 if(k <&#61; s) { // rs
140 for(int i &#61; 1; i <&#61; tp; i&#43;&#43;) {
141 now[p[i]] &#61; rs[now[p[i]]];
142 }
143 l &#61; mid &#43; 1;
144 }
145 else { // ls
146 k -&#61; s;
147 for(int i &#61; 1; i <&#61; tp; i&#43;&#43;) {
148 now[p[i]] &#61; ls[now[p[i]]];
149 }
150 r &#61; mid;
151 }
152 }
153 for(int i &#61; 1; i <&#61; tp; i&#43;&#43;) {
154 vis[p[i]] &#61; 0;
155 }
156 tp &#61; 0;
157 return r;
158 }
159
160 inline void init() {
161 for(int i &#61; 2; i <&#61; n; i&#43;&#43;) {
162 pw[i] &#61; pw[i >> 1] &#43; 1;
163 }
164 for(int j &#61; 1; j <&#61; pw[n]; j&#43;&#43;) {
165 for(int i &#61; 1; i <&#61; n; i&#43;&#43;) {
166 fa[i][j] &#61; fa[fa[i][j - 1]][j - 1];
167 }
168 }
169 return;
170 }
171
172 int main() {
173 int q;
174 scanf("%d%d", &n, &q);
175 for(int i &#61; 1; i <&#61; n; i&#43;&#43;) {
176 scanf("%d", &val[i]);
177 }
178 for(int i &#61; 1, x, y; i ) {
179 scanf("%d%d", &x, &y);
180 add(x, y);
181 add(y, x);
182 }
183 // prework
184
185 DFS(1, 0);
186 init();
187 for(int i &#61; 1; i <&#61; n; i&#43;&#43;) {
188 // [pos[i], ed[i]] insert val[i] 1
189 insert(pos[i], val[i], 1);
190 insert(ed[i] &#43; 1, val[i], -1);
191 }
192
193 for(int i &#61; 1, f, x, y; i <&#61; q; i&#43;&#43;) {
194 scanf("%d%d%d", &f, &x, &y);
195 if(f &#61;&#61; 0) { // change val[x] &#61; y
196 // [pos[x] ed[x]] insert val[x]
197 insert(pos[x], val[x], -1);
198 insert(ed[x] &#43; 1, val[x], 1);
199 insert(pos[x], y, 1);
200 insert(ed[x] &#43; 1, y, -1);
201 val[x] &#61; y;
202 }
203 else { /// ask fth
204 int t &#61; ask(f, x, y);
205 if(t &#61;&#61; -1) {
206 puts("invalid request!");
207 }
208 else {
209 printf("%d\n", t);
210 }
211 }
212 }
213 return 0;
214 }

AC代码

接下来是线段树套线段树的写法。

离散化之后外层值域线段树&#xff0c;内层线段树每个点按照DFS序维护&#xff0c;该点到根的路径上&#xff0c;有多少点的权值在外层树这个范围内。

查询的时候也是值域线段树上二分。利用lca转化成4个内层线段树单点求值再加加减减。

建树的时候&#xff0c;每个点要在外层树上从上往下log个内层树中插入。内层树中要在它的子树插入&#xff0c;又是一段区间。

修改就是跟建树差不多的操作&#xff0c;删去旧的再加上新的。

开了O2还慢的飞起...好歹是过了。

时间复杂度同上。

1 // luogu-judger-enable-o2
2 #include
3 #include
4
5 const int N &#61; 80010, M &#61; 30000010;
6
7 struct Node {
8 int f, x, y;
9 }node[N];
10
11 struct Edge {
12 int nex, v;
13 }edge[N <<1]; int top;
14
15 int e[N], n, num, tot, pw[N], pos[N], ed[N], fa[N][20], d[N], rt[N <<2], temp, val[N], X[N <<1];
16 int tag[M], ls[M], rs[M], sum[M];
17
18 inline void add(int x, int y) {
19 top&#43;&#43;;
20 edge[top].v &#61; y;
21 edge[top].nex &#61; e[x];
22 e[x] &#61; top;
23 return;
24 }
25
26 inline void pushdown(int l, int r, int o) {
27 if(!tag[o]) {
28 return;
29 }
30 if(!ls[o]) {
31 ls[o] &#61; &#43;&#43;tot;
32 }
33 if(!rs[o]) {
34 rs[o] &#61; &#43;&#43;tot;
35 }
36 tag[ls[o]] &#43;&#61; tag[o];
37 tag[rs[o]] &#43;&#61; tag[o];
38 int mid &#61; (l &#43; r) >> 1;
39 sum[ls[o]] &#43;&#61; tag[o] * (mid - l &#43; 1);
40 sum[rs[o]] &#43;&#61; tag[o] * (r - mid);
41 tag[o] &#61; 0;
42 return;
43 }
44
45 void DFS(int x, int f) {
46 fa[x][0] &#61; f;
47 d[x] &#61; d[f] &#43; 1;
48 pos[x] &#61; &#43;&#43;num;
49 for(int i &#61; e[x]; i; i &#61; edge[i].nex) {
50 int y &#61; edge[i].v;
51 if(y !&#61; f) {
52 DFS(y, x);
53 }
54 }
55 ed[x] &#61; num;
56 return;
57 }
58
59 inline void init() {
60 for(int i &#61; 2; i <&#61; n; i&#43;&#43;) {
61 pw[i] &#61; pw[i >> 1] &#43; 1;
62 }
63 for(int j &#61; 1; j <&#61; pw[n]; j&#43;&#43;) {
64 for(int i &#61; 1; i <&#61; n; i&#43;&#43;) {
65 fa[i][j] &#61; fa[fa[i][j - 1]][j - 1];
66 }
67 }
68 return;
69 }
70
71 inline int lca(int x, int y) {
72 if(d[x] > d[y]) {
73 std::swap(x, y);
74 }
75 int t &#61; pw[n];
76 while(t >&#61; 0 && d[y] > d[x]) {
77 if(d[fa[y][t]] >&#61; d[x]) {
78 y &#61; fa[y][t];
79 }
80 t--;
81 }
82 if(x &#61;&#61; y) {
83 return x;
84 }
85 t &#61; pw[n];
86 while(t >&#61; 0 && fa[x][0] !&#61; fa[y][0]) {
87 if(fa[x][t] !&#61; fa[y][t]) {
88 x &#61; fa[x][t];
89 y &#61; fa[y][t];
90 }
91 t--;
92 }
93 return fa[x][0];
94 }
95
96 void Add(int L, int R, int v, int l, int r, int &o) {
97 //printf("add : %d %d %d %d %d %d \n", L, R, v, l, r, o);
98 if(!o) {
99 o &#61; &#43;&#43;tot;
100 }
101 if(L <&#61; l && r <&#61; R) {
102 tag[o] &#43;&#61; v;
103 sum[o] &#43;&#61; (r - l &#43; 1) * v;
104 return;
105 }
106 pushdown(l, r, o);
107 int mid &#61; (l &#43; r) >> 1;
108 if(L <&#61; mid) {
109 Add(L, R, v, l, mid, ls[o]);
110 }
111 if(mid < R) {
112 Add(L, R, v, mid &#43; 1, r, rs[o]);
113 }
114 sum[o] &#61; sum[ls[o]] &#43; sum[rs[o]];
115 return;
116 }
117
118 void insert(int L, int R, int v, int p, int l, int r, int o) {
119 //printf("insert val [%d %d] \n", l, r);
120 Add(L, R, v, 1, n, rt[o]);
121 if(l &#61;&#61; r) {
122 return;
123 }
124 int mid &#61; (l &#43; r) >> 1;
125 if(p <&#61; mid) {
126 insert(L, R, v, p, l, mid, o <<1);
127 }
128 else {
129 insert(L, R, v, p, mid &#43; 1, r, o <<1 | 1);
130 }
131 return;
132 }
133
134 int getSum(int p, int l, int r, int o) {
135 if(!o) {
136 return 0;
137 }
138 if(l &#61;&#61; r) {
139 return sum[o];
140 }
141 int mid &#61; (l &#43; r) >> 1;
142 pushdown(l, r, o);
143 if(p <&#61; mid) {
144 return getSum(p, l, mid, ls[o]);
145 }
146 else {
147 return getSum(p, mid &#43; 1, r, rs[o]);
148 }
149 }
150
151 int Ask(int k, int x, int y, int z, int w, int l, int r, int o) {
152 if(l &#61;&#61; r) {
153 return r;
154 }
155 int s &#61; 0;
156 s &#43;&#61; getSum(x, 1, n, rt[o <<1 | 1]);
157 s &#43;&#61; getSum(y, 1, n, rt[o <<1 | 1]);
158 s -&#61; getSum(z, 1, n, rt[o <<1 | 1]);
159 if(w) {
160 s -&#61; getSum(w, 1, n, rt[o <<1 | 1]);
161 }
162 int mid &#61; (l &#43; r) >> 1;
163 if(k <&#61; s) {
164 return Ask(k, x, y, z, w, mid &#43; 1, r, o <<1 | 1);
165 }
166 else {
167 k -&#61; s;
168 return Ask(k, x, y, z, w, l, mid, o <<1);
169 }
170 }
171
172 inline int ask(int k, int x, int y) {
173 int z &#61; lca(x, y);
174 if(d[x] &#43; d[y] - d[z] * 2 &#43; 1 < k) {
175 return -1;
176 }
177 int w &#61; fa[z][0];
178 x &#61; pos[x];
179 y &#61; pos[y];
180 z &#61; pos[z];
181 w &#61; pos[w];
182 return Ask(k, x, y, z, w, 1, temp, 1);
183 }
184
185 int main() {
186 int q;
187 scanf("%d%d", &n, &q);
188 for(int i &#61; 1; i <&#61; n; i&#43;&#43;) {
189 scanf("%d", &val[i]);
190 X[&#43;&#43;temp] &#61; val[i];
191 }
192 for(int i &#61; 1, x, y; i ) {
193 scanf("%d%d", &x, &y);
194 add(x, y);
195 add(y, x);
196 }
197 for(int i &#61; 1; i <&#61; q; i&#43;&#43;) {
198 scanf("%d%d%d", &node[i].f, &node[i].x, &node[i].y);
199 if(node[i].f &#61;&#61; 0) {
200 X[&#43;&#43;temp] &#61; node[i].y;
201 }
202 }
203 // prework
204 std::sort(X &#43; 1, X &#43; temp &#43; 1);
205 temp &#61; std::unique(X &#43; 1, X &#43; temp &#43; 1) - X - 1;
206 for(int i &#61; 1; i <&#61; n; i&#43;&#43;) {
207 val[i] &#61; std::lower_bound(X &#43; 1, X &#43; temp &#43; 1, val[i]) - X;
208 }
209 for(int i &#61; 1; i <&#61; q; i&#43;&#43;) {
210 if(node[i].f &#61;&#61; 0) {
211 node[i].y &#61; std::lower_bound(X &#43; 1, X &#43; temp &#43; 1, node[i].y) - X;
212 }
213 }
214
215 DFS(1, 0);
216 init();
217 for(int i &#61; 1; i <&#61; n; i&#43;&#43;) {
218 insert(pos[i], ed[i], 1, val[i], 1, temp, 1);
219 }
220 for(int i &#61; 1, f, x, y; i <&#61; q; i&#43;&#43;) {
221 f &#61; node[i].f;
222 x &#61; node[i].x;
223 y &#61; node[i].y;
224 if(f &#61;&#61; 0) { // change
225 insert(pos[x], ed[x], -1, val[x], 1, temp, 1);
226 insert(pos[x], ed[x], 1, y, 1, temp, 1);
227 val[x] &#61; y;
228 }
229 else { // ask fth
230 int t &#61; ask(f, x, y);
231 if(t &#61;&#61; -1) {
232 puts("invalid request!");
233 }
234 else {
235 printf("%d\n", X[t]);
236 }
237 }
238 }
239 return 0;
240 }

AC代码

写的有点乱...

转:https://www.cnblogs.com/huyufeifei/p/10321394.html



推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 判断数组是否全为0_连续子数组的最大和的解题思路及代码方法一_动态规划
    本文介绍了判断数组是否全为0以及求解连续子数组的最大和的解题思路及代码方法一,即动态规划。通过动态规划的方法,可以找出连续子数组的最大和,具体思路是尽量选择正数的部分,遇到负数则不选择进去,遇到正数则保留并继续考察。本文给出了状态定义和状态转移方程,并提供了具体的代码实现。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
author-avatar
孜雪颖2000
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有