1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3427 Solved: 1429
[ Submit][ Status]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
分析:
裸的树链剖分。注意一下,输入的节点权值的下标要改为在线段树上的节点下标。
1 #include <set> 2 #include <map> 3 #include <list> 4 #include <cmath> 5 #include <queue> 6 #include <stack> 7 #include <string> 8 #include <vector> 9 #include <cstdio> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 14 using namespace std; 15 16 typedef long long ll; 17 typedef unsigned long long ull; 18 19 #define debug puts("here") 20 #define rep(i,n) for(int i=0;i<n;i++) 21 #define rep1(i,n) for(int i=1;i<=n;i++) 22 #define REP(i,a,b) for(int i=a;i<=b;i++) 23 #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++) 24 #define pb push_back 25 #define RD(n) scanf("%d",&n) 26 #define RD2(x,y) scanf("%d%d",&x,&y) 27 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) 28 #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) 29 #define All(vec) vec.begin(),vec.end() 30 #define MP make_pair 31 #define PII pair<int,int> 32 #define PQ priority_queue 33 #define cmax(x,y) x = max(x,y) 34 #define cmin(x,y) x = min(x,y) 35 #define Clear(x) memset(x,0,sizeof(x)) 36 /* 37 38 #pragma comment(linker, "/STACK:1024000000,1024000000") 39 40 int size = 256 << 20; // 256MB 41 char *p = (char*)malloc(size) + size; 42 __asm__("movl %0, %%esp\n" :: "r"(p) ); 43 44 */ 45 46 /******** program ********************/ 47 48 const int MAXN = 100005; 49 const int INF = 1e9; 50 51 int val[MAXN]; 52 int po[MAXN],tol; 53 int sz[MAXN],dep[MAXN],fa[MAXN],son[MAXN],tid[MAXN],top[MAXN]; 54 bool use[MAXN]; 55 int tot; 56 int mx,msum; 57 58 struct node{ 59 int y,next; 60 }edge[MAXN]; 61 62 struct Tree{ 63 int l,r,mx,sum; 64 inline int mid(){ 65 return (l+r)>>1; 66 } 67 }tree[MAXN<<2]; 68 69 inline void add(int x,int y){ 70 edge[++tol].y = y; 71 edge[tol].next = po[x]; 72 po[x] = tol; 73 } 74 75 void dfsFind(int x,int pa,int depth){ 76 use[x] = true; 77 dep[x] = depth; 78 fa[x] = pa; 79 sz[x] = 1; 80 son[x] = 0; 81 82 for(int i=po[x];i;i=edge[i].next){ 83 int y = edge[i].y; 84 if(use[y])continue; 85 dfsFind(y,x,depth+1); 86 sz[x] += sz[y]; 87 if(sz[y]>sz[ son[x] ]) 88 son[x] = y; 89 } 90 } 91 92 void dfsCon(int x,int pa){ 93 use[x] = true; 94 tid[x] = ++ tot; 95 top[x] = pa; 96 if(son[x]) 97 dfsCon(son[x],pa); 98 for(int i=po[x];i;i=edge[i].next){ 99 int y = edge[i].y; 100 if(use[y])continue; 101 dfsCon(y,y); 102 } 103 } 104 105 inline void update(int rt){ 106 tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum; 107 tree[rt].mx = max( tree[rt<<1].mx , tree[rt<<1|1].mx ); 108 } 109 110 void build(int l,int r,int rt){ 111 tree[rt].l = l; 112 tree[rt].r = r; 113 if(l==r){ 114 tree[rt].sum = tree[rt].mx = val[l]; 115 return; 116 } 117 int mid = tree[rt].mid(); 118 build(l,mid,rt<<1); 119 build(mid+1,r,rt<<1|1); 120 121 update(rt); 122 } 123 124 void modify(int pos,int c,int rt){ 125 if(tree[rt].l==tree[rt].r){ 126 tree[rt].sum = tree[rt].mx = c; 127 return; 128 } 129 int mid = tree[rt].mid(); 130 if(pos<=mid) 131 modify(pos,c,rt<<1); 132 else 133 modify(pos,c,rt<<1|1); 134 135 update(rt); 136 } 137 138 void ask(int l,int r,int rt){ 139 if(tree[rt].l==l&&tree[rt].r==r){ 140 mx = max(mx,tree[rt].mx); 141 //cmax( mx , tree[rt].mx ); 142 msum += tree[rt].sum; 143 return; 144 } 145 int mid = tree[rt].mid(); 146 if(r<=mid) 147 ask(l,r,rt<<1); 148 else if(l>mid) 149 ask(l,r,rt<<1|1); 150 else{ 151 ask(l,mid,rt<<1); 152 ask(mid+1,r,rt<<1|1); 153 } 154 } 155 156 int main(){ 157 158 #ifndef ONLINE_JUDGE 159 freopen("sum.in","r",stdin); 160 //freopen("sum.out","w",stdout); 161 #endif 162 163 int n,m,x,y; 164 while(cin>>n){ 165 Clear(po); 166 tol = 1; 167 168 REP(i,2,n){ 169 RD2(x,y); 170 add(x,y); 171 add(y,x); 172 } 173 174 Clear(use); 175 dfsFind(1,1,1); 176 177 Clear(use); 178 tot = 0; 179 dfsCon(1,1); 180 181 rep1(i,n){ 182 RD(y); 183 val[ tid[i] ] = y; 184 } 185 186 build(1,n,1); 187 188 RD(m); 189 char op[10]; 190 while(m--){ 191 scanf("%s%d%d",op,&x,&y); 192 if(op[1]=='H'){ 193 modify(tid[x],y,1); 194 }else{ 195 mx = -INF; 196 msum = 0; 197 198 while( top[x] != top[y] ){ 199 if( dep[ top[x] ] < dep[ top[y] ] ) 200 swap(x,y); 201 ask( tid[ top[x] ] , tid[x] , 1 ); 202 x = fa[ top[x] ]; 203 } 204 if(dep[x]>dep[y]) 205 swap(x,y); 206 ask(tid[x],tid[y],1); 207 208 printf("%d\n",op[1]=='M'?mx:msum); 209 } 210 } 211 } 212 213 return 0; 214 }
SPOJ 6779. Can you answer these queries VII
给定一棵点权树,支持以下两种操作:
- 1 u v: 询问 u, v 路径上的最大子序列和。((允许不取)
- 2 u v d: 将 u, v 路径上的所有点的点权都修改为 d。
Ural 1553. Caves and Tunnels
给定一个 n 个结点的带点权的树,要求维护以下两种操作:
- I u d: 将结点 u 的权值 + d。
- G u v: 询问 u、v 所在路径上点权的最大值。
spoj 2798 Query on a tree again!
给出一棵树,节点只有两种颜色,初始时颜色为白色。有两种操作:
- 0 i :询问节点1到i的路径上第一个是黑色的节点,没有为-1.
- 1 v:节点v颜色反置。