3531: [Sdoi2014]旅行
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 323 Solved: 192
[Submit][Status]
Description
S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足
从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表
各种宗教,
S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个
城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。
Input
输入的第一行包含整数N,Q依次表示城市数和事件数。
接下来N行,第i+l行两个整数Wi,Ci依次表示记录开始之前,城市i的
评级和信仰。
接下来N-1行每行两个整数x,y表示一条双向道路。
接下来Q行,每行一个操作,格式如上所述。
Output
对每个QS和QM事件,输出一行,表示旅行者记下的数字。
Sample Input
3 1
2 3
1 2
3 3
5 1
1 2
1 3
3 4
3 5
QS 1 5
CC 3 1
QS 1 5
CW 3 3
QS 1 5
QM 2 4
Sample Output
9
11
3
HINT
N,Q < =10^5 , C < =10^5
数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时
刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。
Source
这题题意是每个点有a,b两个值, 询问路径x,y中a值跟x相同的b值的最大值或者和
树链剖分,给每个a值建一颗线段树,然后动态开点,复杂度log^2(n)
没啥trick
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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | /* Author:wuhuajun */ #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define lson l, mid, seg[rt].l #define rson mid+1, r, seg[rt].r using namespace std; typedef long long ll; typedef double dd; const int maxn=200010; const int maxq = 20000010; int edge, n, fa[maxn], sz[maxn], son[maxn], dep[maxn], hash[maxn], top[maxn]; int h[maxn], num , x, y, tx, ty, Q, a[maxn], b[maxn], node, rel; char s[22]; struct Edge { int to, ne; } e[maxn * 2]; struct Seg { int maxx, sum, l, r; void clear() { maxx = -1000000000; sum = 0; } } seg[maxq], ret, ans; void close() { exit (0); } void addedge( int x, int y) { e[edge].to = y; e[edge].ne = h[x]; h[x] = edge++; } void dfs( int k, int from) { sz[k] = 1; son[k] = 0; dep[k] = dep[from] + 1; for ( int p=h[k];p!=-1;p=e[p].ne) { int to = e[p].to; if (from == to) continue ; fa[to] = k; dfs(to, k); sz[k] += sz[to]; if (sz[to] > sz[son[k]]) son[k] = to; } } void build( int k, int from) { hash[k] = ++num; top[k] = from; if (son[k]) build(son[k], from); for ( int p=h[k];p!=-1;p=e[p].ne) { int to = e[p].to; if (to != fa[k] && to != son[k]) build(to, to); } } //{{{Segment部分 void new_node( int rt) { if (seg[rt].l == 0) seg[rt].l = ++node; if (seg[rt].r == 0) seg[rt].r = ++node; } Seg update(Seg a,Seg b) { Seg c; c.sum = a.sum + b.sum; c.maxx = max(a.maxx, b.maxx); return c; } void pushup( int rt) { seg[rt].maxx = max(seg[seg[rt].l].maxx, seg[seg[rt].r].maxx); seg[rt].sum = seg[seg[rt].l].sum + seg[seg[rt].r].sum; } void change( int L, int R, int val, int l, int r, int rt) { new_node(rt); if (L <= l && r <= R) { seg[rt].sum = seg[rt].maxx = val; return ; } int mid = (l + r) >> 1; if (L <= mid) change(L,R,val,lson); if (mid + 1 <= R) change(L,R,val,rson); pushup(rt); } Seg query( int L, int R, int l, int r, int rt) { new_node(rt); if (L <= l && r <= R) { return seg[rt]; } int mid = (l + r) >> 1; Seg ans; ans.clear(); if (L <= mid) ans = update(ans, query(L,R,lson)); if (mid + 1 <= R) ans = update(ans, query(L,R,rson)); return ans; } //}}} Seg get_ans() { tx = top[x]; ty = top[y]; ans.clear(); while (tx != ty) { if (dep[tx] < dep[ty]) { swap(tx, ty); swap(x, y); } ans = update(ans, query(hash[tx], hash[x], 1, n, rel)); x = fa[tx]; tx = top[x]; } if (dep[x] > dep[y]) swap(x, y); return update(ans, query(hash[x], hash[y], 1, n, rel)); } void init() { scanf ( "%d %d" ,&n, &Q); memset (h,-1, sizeof (h)); for ( int i=1;i<=n;i++) { scanf ( "%d %d" ,&b[i], &a[i]); } for ( int i=1;i<=n-1;i++) { scanf ( "%d %d" ,&x, &y); addedge(x, y); addedge(y, x); } for ( int i=1;i<=n;i++) scanf ( "%d" , &a[i]); dfs(1, 0); build(1, 1); node = n; /* for (int i=1;i<=n;i++) { printf("i:%d top:%d hash:%d\n",i, top[i], hash[i]); } */ for ( int i=1;i<=n;i++) change(hash[i], hash[i], b[i], 1, n, a[i]); // a -> 宗教 b -> 评级 while (Q--) { scanf ( "%s %d %d" , s, &x, &y); if (s[1] == 'C' ) { change(hash[x], hash[x], 0, 1, n, a[x]); //把本属于宗教a[i]的x点评级改成0; a[x] = y; change(hash[x], hash[x], b[x], 1, n, a[x]); //把本属于宗教a[i]的x点评级改成现有的 } if (s[1] == 'W' ) { b[x] = y; change(hash[x], hash[x], y, 1, n, a[x]); } if (s[1] == 'S' ) { rel = a[x]; ret = get_ans(); printf ( "%d\n" , ret.sum); } if (s[1] == 'M' ) { rel = a[x]; ret = get_ans(); printf ( "%d\n" , ret.maxx); } } } int main () { init(); close(); return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 从零实现富文本编辑器#3-基于Delta的线性数据结构模型
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 长文讲解 MCP 和案例实战
· Hangfire Redis 实现秒级定时任务,使用 CQRS 实现动态执行代码
· 使用TypeScript开发微信小程序(云开发)-入门篇
· 没几个人需要了解的JDK知识,我却花了3天时间研究
· C#高性能开发之类型系统:从 C# 7.0 到 C# 14 的类型系统演进全景
· 管理100个小程序-很难吗
· 在SqlSugar的开发框架中增加对低代码EAV模型(实体-属性-值)的WebAPI实现支持