题目一 : SPOJ 375 Query On a Tree
http://www.spoj.com/problems/QTREE/
给一个树,求a,b路径上最大边权,或者修改a,b边权为t。
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 7 using namespace std; 8 const int maxn = 200000 + 5; 9 10 int N,pos=0; 11 char ss[50]; 12 13 struct SegmentTree{ 14 int l,r,flag; 15 int maxv,minv; 16 }Node[maxn * 10]; 17 18 int e[maxn][4]; 19 int size[maxn],dep[maxn],top[maxn],son[maxn]; 20 int fa[maxn],Segnum[maxn],Treenum[maxn]; 21 22 int tot = 0; 23 int first[maxn],next[maxn*2]; 24 int u[maxn*2],v[maxn*2]; 25 26 void clear(); 27 void change(int&,int&); 28 void Add(int,int); 29 void dfs_1(int,int,int); 30 void dfs_2(int,int); 31 void build(int,int,int); 32 void update(int,int,int,int); 33 int query(int,int,int); 34 int find_max(int,int); 35 void rever(int,int,int); 36 void get_rever(int,int); 37 void pushdown(int); 38 void pushup(int); 39 40 int main(){ 41 int tcase; 42 scanf("%d",&tcase); 43 while(tcase --){ 44 clear(); 45 int x,y,z; 46 scanf("%d",&N); 47 for(int i = 1;i < N;++ i){ 48 scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); 49 Add(e[i][0],e[i][1]); 50 Add(e[i][1],e[i][0]); 51 } 52 53 dfs_1(1,0,1); 54 dfs_2(1,1); 55 build(1,1,N); 56 for(int i = 1;i < N;++ i){ 57 if(dep[e[i][0]] > dep[e[i][1]]) 58 swap(e[i][0],e[i][1]); 59 update(1,Segnum[e[i][1]],Segnum[e[i][1]],e[i][2]); 60 } 61 while(1){ 62 scanf("%s",ss); 63 if(ss[0] == ‘D‘) 64 break; 65 scanf("%d%d",&x,&y); 66 if(ss[0] == ‘C‘){ 67 update(1,Segnum[e[x][1]],Segnum[e[x][1]],y); 68 } 69 else if(ss[0] == ‘Q‘){ 70 printf("%d\n",find_max(x,y)); 71 } 72 else if(ss[0] == ‘N‘){ 73 get_rever(x,y); 74 } 75 } 76 } 77 return 0; 78 } 79 80 void clear(){ 81 pos = 0;tot = 0; 82 memset(son,0,sizeof son); 83 memset(first,0,sizeof first); 84 } 85 void Add(int s,int t){ 86 ++ tot; 87 u[tot] = s;v[tot] = t; 88 next[tot] = first[u[tot]]; 89 first[u[tot]] = tot; 90 } 91 void dfs_1(int now,int f,int depth){ 92 size[now] = 1; 93 fa[now] = f; 94 dep[now] = depth; 95 96 for(int i = first[now];i;i = next[i]){ 97 if(v[i] != f){ 98 dfs_1(v[i],now,depth + 1); 99 size[now] += size[v[i]]; 100 if(!son[now] || size[v[i]] > size[son[now]]) 101 son[now] = v[i]; 102 } 103 } 104 return; 105 } 106 107 void dfs_2(int now,int ances){ 108 top[now] = ances; 109 Segnum[now] = ++ pos; 110 Treenum[Segnum[now]] = now; 111 112 if(!son[now])return; 113 dfs_2(son[now],ances); 114 115 for(int i = first[now];i;i = next[i]){ 116 if(v[i] != son[now] && v[i] != fa[now]){ 117 dfs_2(v[i],v[i]); 118 } 119 } 120 return; 121 } 122 123 void build(int o,int l,int r){ 124 Node[o].l = l; 125 Node[o].r = r; 126 Node[o].minv = Node[o].maxv = 0; 127 Node[o].flag = 0; 128 if(l == r) 129 return; 130 int Mid = (l + r) >> 1; 131 build(o<<1,l,Mid); 132 build(o<<1|1,Mid+1,r); 133 } 134 135 void update(int o,int l,int r,int v){ 136 if(Node[o].l == l && Node[o].r == r){ 137 Node[o].minv = Node[o].maxv = v; 138 Node[o].flag = 0; 139 return; 140 } 141 int Mid = (Node[o].l + Node[o].r) >> 1; 142 pushdown(o); 143 if(r <= Mid) 144 update(o<<1,l,r,v); 145 else if(l > Mid) 146 update(o<<1|1,l,r,v); 147 pushup(o); 148 } 149 void pushdown(int o){ 150 if(Node[o].l == Node[o].r) 151 return; 152 int lc = o << 1,rc = o << 1 | 1; 153 if(Node[o].flag){ 154 Node[o].flag = 0; 155 Node[lc].flag ^= 1; 156 Node[rc].flag ^= 1; 157 change(Node[rc].minv,Node[rc].maxv); 158 change(Node[lc].maxv,Node[lc].minv); 159 } 160 } 161 void pushup(int o){ 162 int lc = o << 1,rc = o << 1 | 1; 163 Node[o].maxv = max(Node[lc].maxv,Node[rc].maxv); 164 Node[o].minv = min(Node[lc].minv,Node[rc].minv); 165 } 166 167 int query(int o,int l,int r){ 168 if(Node[o].l == l && Node[o].r == r){ 169 return Node[o].maxv; 170 } 171 int Mid = (Node[o].l + Node[o].r) >> 1; 172 pushdown(o); 173 if(r <= Mid) 174 return query(o<<1,l,r); 175 else if(l > Mid) 176 return query(o<<1|1,l,r); 177 else 178 return max(query(o<<1,l,Mid),query(o<<1|1,Mid+1,r)); 179 pushup(o); 180 } 181 void rever(int o,int l,int r){ 182 if(Node[o].l == l && Node[o].r == r){ 183 change(Node[o].maxv,Node[o].minv); 184 Node[o].flag ^= 1; 185 return; 186 } 187 int Mid = (Node[o].l + Node[o].r) >> 1; 188 pushdown(o); 189 if(r <= Mid) 190 rever(o<<1,l,r); 191 else if(l > Mid) 192 rever(o<<1|1,l,r); 193 else{ 194 rever(o<<1,l,Mid); 195 rever(o<<1|1,Mid+1,r); 196 } 197 pushup(o); 198 } 199 int find_max(int x,int y){ 200 int f1 = top[x],f2 = top[y]; 201 int ret = -100000; 202 203 while(f1 != f2){ 204 if(dep[f1] < dep[f2]){ 205 swap(f1,f2); 206 swap(x,y); 207 } 208 ret = max(ret,query(1,Segnum[f1],Segnum[x])); 209 x = fa[f1];f1 = top[x]; 210 } 211 212 if(x == y)return ret; 213 if(dep[x] < dep[y]){ 214 ret = max(ret,query(1,Segnum[son[x]],Segnum[y])); 215 } 216 else{ 217 ret = max(ret,query(1,Segnum[son[y]],Segnum[x])); 218 } 219 220 return ret; 221 } 222 223 void get_rever(int x,int y){ 224 int f1 = top[x],f2 = top[y]; 225 226 while(f1 != f2){ 227 if(dep[f1] < dep[f2]){ 228 swap(f1,f2); 229 swap(x,y); 230 } 231 rever(1,Segnum[f1],Segnum[x]); 232 x = fa[f1];f1 = top[x]; 233 } 234 if(x == y)return;//如果是针对边的操作, 这个东西不能少。。 235 if(dep[x] < dep[y]){ 236 rever(1,Segnum[son[x]],Segnum[y]);//如果是边权,注意这里的写法。要下放。 237 } 238 else{ 239 rever(1,Segnum[son[y]],Segnum[x]); 240 } 241 return; 242 } 243 244 void change(int &a,int &b){ 245 int tp1 = a,tp2 = b; 246 a = -tp2;b = -tp1; 247 return; 248 }
树链剖分
时间: 2024-10-17 12:52:06