「luogu3313」[SDOI2014] 旅行
题目大意 :
有 n 个城市连成一棵树, 每个城市有两个关键字, 一个是该城市的宗教, 另一个是城市的评级;
旅行者要在城市间旅行, 他只会在和自己宗教相同的城市留宿;
维护四个树上操作 {
1. “CC x c“ :城市 x 的居民全体改信了 c 教;
2. “CW x w“ :城市 x 的评级调整为 w;
3. “QS x y“ :一位旅行者从城市 x 出发,到城市 y,并记下了途中留宿过的城市的评级总和;
4. “QM x y“:一位旅行者从城市 x 出发,到城市 y ,并记下了途中留宿过的城市的评级最大值;
}
(旅行者信的教和旅行的终点相同;
树剖+线段树 : 如果对每种宗教都开一颗线段树, 内存爆炸 -------> 考虑动态开点
动态开点 {
在这道题中, 可以考虑给每一种宗教开一个线段树, 但一开始不需要开满;
对于每一个第一次出现的宗教或者一个宗教里的一个新城市, 都把他当做一个新节点;
对于单次操作 时间复杂度和空间复杂度都是 O(log n) , 因为对于一种宗教最多有n个节点, 在线段树里找到一个节点最多 logn+1 次;
}
代码如下 :
1 //Author : 15owzLy1 2 //luogu3313.cpp 3 //2018 12 09 14:24:30 4 #include <iostream> 5 #include <cstdio> 6 #include <cstring> 7 #include <algorithm> 8 #define INF 2100000000 9 typedef long long ll; 10 typedef double db; 11 template<typename T>inline void read(T &_) { 12 _=0;int __=0;char ___=getchar(); 13 while(___<'0'||___>'9')__|=(___=='-'),___=getchar(); 14 while(___>='0'&&___<='9')_=(_<<1)+(_<<3)+(___^48),___=getchar(); 15 _=__?-_:_; 16 } 17 18 const int N = (int)1e5+5; 19 struct edge { 20 int next, to; 21 }edge[N<<1]; 22 int head[N], cnt=1, c[N], w[N]; 23 int n, q, hson[N], size[N], dfn[N], front[N], dep[N], fa[N]; 24 25 class Segment_Tree { 26 private : 27 struct node { 28 int sum, max, l, r; 29 #define t a[rt] 30 #define lson a[a[rt].l] 31 #define rson a[a[rt].r] 32 }a[N*20]; 33 int cnt; 34 inline void push_up(int rt) { 35 t.sum=lson.sum+rson.sum; 36 t.max=std::max(lson.max, rson.max); 37 } 38 public : 39 int root[N]; 40 void update(int &rt, int del, int tl, int tr, int pos) { 41 if(!rt) rt=++cnt; 42 if(tl==tr) { t.max=t.sum=del; return ; } 43 int mid=(tl+tr)>>1; 44 if(mid>=pos) update(t.l, del, tl, mid, pos); 45 else update(t.r, del, mid+1, tr, pos); 46 push_up(rt); 47 } 48 void remove(int &rt, int tl, int tr, int pos) { 49 if(tl==tr) { rt=t.sum=t.max=0; return ; } 50 int mid=(tl+tr)>>1; 51 if(mid>=pos) remove(t.l, tl, mid, pos); 52 else remove(t.r, mid+1, tr, pos); 53 push_up(rt); 54 } 55 int query_sum(int rt, int l, int r, int tl, int tr) { 56 if(l<=tl&&tr<=r) return t.sum; 57 int mid=(tl+tr)>>1, ret=0; 58 if(mid>=l) ret+=query_sum(t.l, l, r, tl, mid); 59 if(mid<r) ret+=query_sum(t.r, l, r, mid+1, tr); 60 return ret; 61 } 62 int query_max(int rt, int l, int r, int tl, int tr) { 63 if(l<=tl&&tr<=r) return t.max; 64 int mid=(tl+tr)>>1, ret=0; 65 if(mid>=l) ret=std::max(ret, query_max(t.l, l, r, tl, mid)); 66 if(mid<r) ret=std::max(ret, query_max(t.r, l, r, mid+1, tr)); 67 return ret; 68 } 69 }T; 70 71 inline void jb(int u, int v) { 72 edge[++cnt].to=v; 73 edge[cnt].next=head[u]; 74 head[u]=cnt; 75 } 76 77 void get_hson(int u) { 78 size[u]=1; 79 for(int i=head[u];i;i=edge[i].next) { 80 int v=edge[i].to; 81 if(v==fa[u]) continue; 82 fa[v]=u, dep[v]=dep[u]+1; 83 get_hson(v); 84 size[u]+=size[v]; 85 if(size[v]>=size[hson[u]]) hson[u]=v; 86 } 87 } 88 89 void get_front(int u, int father) { 90 dfn[u]=++dfn[0], front[u]=father; 91 if(hson[u]) get_front(hson[u], father); 92 for(int i=head[u];i;i=edge[i].next) { 93 int v=edge[i].to; 94 if(v==fa[u]||v==hson[u]) continue; 95 get_front(v, v); 96 } 97 } 98 99 inline int query_sum(int u, int v) { 100 int ret=0, cl=c[v]; 101 while(front[u]!=front[v]) { 102 if(dep[front[u]]>dep[front[v]]) std::swap(u, v); 103 ret+=T.query_sum(T.root[cl], dfn[front[v]], dfn[v], 1, n); 104 v=fa[front[v]]; 105 } 106 if(dep[u]>dep[v]) std::swap(u, v); 107 ret+=T.query_sum(T.root[cl], dfn[u], dfn[v], 1, n); 108 return ret; 109 } 110 111 inline int query_max(int u, int v) { 112 int ret=0, cl=c[v]; 113 while(front[u]!=front[v]) { 114 if(dep[front[u]]>dep[front[v]]) std::swap(u, v); 115 ret=std::max(ret, T.query_max(T.root[cl], dfn[front[v]], dfn[v], 1, n)); 116 v=fa[front[v]]; 117 } 118 if(dep[u]>dep[v]) std::swap(u, v); 119 ret=std::max(ret, T.query_max(T.root[cl], dfn[u], dfn[v], 1, n)); 120 return ret; 121 } 122 123 int main() { 124 #ifndef ONLINE_JUDGE 125 freopen("luogu3313.in","r",stdin); 126 freopen("luogu3313.out","w",stdout); 127 #endif 128 char opt[3]; 129 int x, y; 130 read(n), read(q); 131 for(int i=1;i<=n;i++) read(w[i]), read(c[i]); 132 for(int i=1;i<n;i++) read(x), read(y), jb(x, y), jb(y, x); 133 get_hson(1); get_front(1, 1); 134 for(int i=1;i<=n;i++) 135 T.update(T.root[c[i]], w[i], 1, n, dfn[i]); 136 137 while(q--) { 138 scanf("%s", opt); 139 read(x), read(y); 140 if(opt[0]=='C') { 141 //change C change W 142 if(opt[1]=='C') { 143 T.remove(T.root[c[x]], 1, n, dfn[x]); 144 c[x]=y; 145 T.update(T.root[c[x]], w[x], 1, n, dfn[x]); 146 } 147 else T.update(T.root[c[x]], y, 1, n, dfn[x]), w[x]=y; 148 } 149 else { 150 //query S query W 151 if(opt[1]=='S') printf("%d\n", query_sum(x, y)); 152 else printf("%d\n", query_max(x, y)); 153 } 154 } 155 return 0; 156 }