BZOJ3531: [Sdoi2014]旅行
2018-02-27 19:55
429 查看
3531: [Sdoi2014]旅行
Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 2801 Solved: 1210
[Submit][Status][Discuss]
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
5 6 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
8 9 11 3
HINT
N,Q < =10^5 , C < =10^5数据保证对所有QS和QM事件,起点和终点城市的信仰相同;在任意时
刻,城市的评级总是不大于10^4的正整数,且宗教值不大于C。
Source
Round 1 Day 1题解
如果我能在2014年参加省选的话。。。。(快醒醒吧起来搬砖了!)动态加点线段树 + 树剖。
太裸辣。。。
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> inline int lowbit(int x){return x & -x;} inline int max(int a, int b){return a > b ? a : b;} inline int min(int a, int b){return a < b ? a : b;} inline void swap(int &x, int &y){int tmp = x;x = y;y = tmp;} inline void read(int &x) { x = 0;char ch = getchar(), c = ch; while(ch < '0' || ch > '9') c = ch, ch = getchar(); while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); if(c == '-') x = -x; } const int INF = 0x3f3f3f3f; const int MAXN = 100000 + 10; int n, q, type[MAXN], w[MAXN]; // Graph struct Edge { int v,nxt; Edge(int _v, int _nxt){v = _v, nxt = _nxt;} Edge(){} }edge[MAXN << 1]; int head[MAXN], cnt; inline void insert(int a, int b) { edge[++ cnt] = Edge(b, head[a]); head[a] = cnt; } //Division int tim, rank[MAXN], tid[MAXN], son[MAXN], size[MAXN], deep[MAXN], fa[MAXN], top[MAXN]; void dfs1(int x) { size[x] = 1; for(int pos = head[x];pos;pos = edge[pos].nxt) { int v = edge[pos].v; if(v == fa[x]) continue; fa[v] = x, deep[v] = deep[x] + 1, dfs1(v), size[x] += size[v]; if(son[x] == -1 || size[son[x]] < size[v]) son[x] = v; } } void dfs2(int x, int tp) { top[x] = tp, tid[x] = ++ tim, rank[tim] = x; if(son[x] == -1) return; dfs2(son[x], tp); for(int pos = head[x];pos;pos = edge[pos].nxt) { int v = edge[pos].v; if(v == fa[x]) continue; if(v == son[x]) continue; dfs2(v, v); } } //Sgt struct Node { int tag, sum, ma, ls, rs; Node(){sum = ma = ls = rs = 0;tag = -1;} }node[MAXN << 5]; int tot, root[MAXN]; int newnode(){return ++ tot;} Node merge(Node &re, Node a, Node b) { if(a.tag == -1) re.sum = b.sum, re.ma = b.ma, re.tag = b.tag; else if(b.tag == -1) re.sum = a.sum, re.ma = a.ma, re.tag = a.tag; else re.sum = a.sum + b.sum, re.ma = max(a.ma, b.ma), re.tag = 1; } void modify(int p, int k, int &o, int l = 1, int r = tim) { if(!o) o = newnode(), node[o].tag = 1; if(l == r && l == p) { node[o].sum = node[o].ma = k, node[o].tag = 1; return; } int mid = (l + r) >> 1; if(p <= mid) modify(p, k, node[o].ls, l, mid); else modify(p, k, node[o].rs, mid + 1, r); merge(node[o], node[node[o].ls], node[node[o].rs]); } Node ask(int ll, int rr, int o, int l = 1, int r = tim) { Node re; if(!o) return re; if(ll <= l && rr >= r) return node[o]; int mid = (l + r) >> 1; Node a, b; if(mid >= ll) a = ask(ll, rr, node[o].ls, l, mid); if(mid < rr) b = ask(ll, rr, node[o].rs, mid + 1, r); merge(re, a, b); return re; } Node query(int x, int y) { int t = type[x]; int f1 = top[x], f2 = top[y]; Node re, tmp; while(f1 != f2) { if(deep[f1] < deep[f2]) swap(f1, f2), swap(x, y); tmp = ask(tid[f1], tid[x], root[t]); merge(re, re, tmp); x = fa[f1], f1 = top[x]; } if(deep[x] > deep[y]) swap(x, y); tmp = ask(tid[x], tid[y],root[t]); merge(re, re, tmp); return re; } int tmp1,tmp2; int main() { memset(son, -1, sizeof(son)); read(n), read(q); for(int i = 1;i <= n;++ i) read(w[i]), read(type[i]); for(int i = 1;i < n;++ i) read(tmp1), read(tmp2), insert(tmp1, tmp2), insert(tmp2, tmp1); dfs1(1), dfs2(1, 1); for(int i = 1;i <= n;++ i) modify(tid[i], w[i], root[type[i]]); char s[10]; for(int i = 1;i <= q;++ i) { scanf("%s", s + 1);read(tmp1), read(tmp2); if(s[2] == 'C') modify(tid[tmp1], 0, root[type[tmp1]]), modify(tid[tmp1], w[tmp1], root[type[tmp1] = tmp2]); else if(s[2] == 'W') modify(tid[tmp1], w[tmp1] = tmp2, root[type[tmp1]]); else if(s[1] == 'Q') { Node tmp = query(tmp1, tmp2); if(s[2] == 'S') printf("%d\n", tmp.sum); else if(s[2] == 'M') printf("%d\n", tmp.ma); } } return 0; }
相关文章推荐
- bzoj3531 [Sdoi2014]旅行 【树链剖分+线段树动态开点】
- bzoj3531 [Sdoi2014]旅行 树链剖分+动态开线段树
- BZOJ3531: [Sdoi2014]旅行
- BZOJ3531: [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行 【树剖 + 线段树】
- Bzoj3531:[Sdoi2014]旅行:树链剖分+动态开点线段树
- [Sdoi 2014] bzoj3531 旅行 [树链剖分]
- bzoj3531: [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行——树剖+动态开点线段树
- bzoj3531: [Sdoi2014]旅行
- Bzoj3531: [Sdoi2014]旅行
- bzoj3531[Sdoi2014]旅行
- bzoj3531: [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行
- BZOJ3531 [Sdoi2014]旅行
- bzoj3531 [Sdoi2014]旅行(树链剖分+动态开点线段树)
- BZOJ3531 【Sdoi2014】旅行
- bzoj3531 [Sdoi2014]旅行 树链剖分 线段树
- bzoj3531 [Sdoi2014]旅行
- bzoj3531【SDOI2014】旅行