【ZJOI2008】【BZOJ1036】树的统计Count
2015-03-11 19:00
447 查看
开学就被送去开学考
寒假一点文化课都没搞你还考个毛(╯‵□′)╯︵┻━┻
最后果然还是挂了(不过至少还没出班里前十= =)
回机房第一天想了想决定再去写一个沙茶链剖
题目描述 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 Description
输入文件的第一行为一个整数n,表示节点的个数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出描述 Output Description
样例输入 Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
样例输出 Sample Output
4
1
2
2
10
6
5
6
5
16
数据范围及提示 Data Size & Hint
对于100%的数据,保证1≤\len≤\le30000,0≤\leq≤\le200000;中途操作中保证每个节点的权值w在-30000到30000之间。
想不到当年的浙江省选也会出裸题233
代码奇丑无比,不但长而且速度也比较慢(反正能AC就不管那么多了╮(╯▽╰)╭)
寒假一点文化课都没搞你还考个毛(╯‵□′)╯︵┻━┻
最后果然还是挂了(不过至少还没出班里前十= =)
回机房第一天想了想决定再去写一个沙茶链剖
题目描述 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 Description
输入文件的第一行为一个整数n,表示节点的个数。
[code] 接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。 接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。 接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
输出描述 Output Description
[code] 对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
样例输入 Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
样例输出 Sample Output
4
1
2
2
10
6
5
6
5
16
数据范围及提示 Data Size & Hint
对于100%的数据,保证1≤\len≤\le30000,0≤\leq≤\le200000;中途操作中保证每个节点的权值w在-30000到30000之间。
想不到当年的浙江省选也会出裸题233
代码奇丑无比,不但长而且速度也比较慢(反正能AC就不管那么多了╮(╯▽╰)╭)
[code]#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define MAXINT 0x7fffffff #define MAXN 100010 #define lchild rt<<1,l,mid #define rchild rt<<1|1,mid+1,r #define ln rt<<1 #define rn rt<<1|1 using namespace std; int w[MAXN]; int size[MAXN],deep[MAXN],chain[MAXN],num[MAXN],fa[MAXN][18]; bool vis[MAXN]; int top,tp; int a,b; int u,v; int n,q; char ch[6]; struct edge { edge *next; int to; }*prev[MAXN],e[MAXN*2]; struct seg { int maxn; int sum; int l; int r; }tree[MAXN*4]; void insert(int u,int v) { e[++top].to=v; e[top].next=prev[u]; prev[u]=&e[top]; } void dfs1(int x) { size[x]=1; vis[x]=1; for (int i=1;i<=17;i++) { if (deep[x]<(1<<i)) break; fa[x][i]=fa[fa[x][i-1]][i-1]; } for (edge *i=prev[x];i;i=i->next) { int t=i->to; if (vis[t]) continue; deep[t]=deep[x]+1; fa[t][0]=x; dfs1(t); size[x]+=size[t]; } } void dfs2(int x,int last) { chain[x]=last; num[x]=++tp; int t=0; for (edge *i=prev[x];i;i=i->next) if (deep[i->to]>deep[x]&&size[t]<size[i->to]) t=i->to; if (!t) return; dfs2(t,last); for (edge *i=prev[x];i;i=i->next) if (deep[i->to]>deep[x]&&i->to!=t) dfs2(i->to,i->to); } void build(int rt=1,int l=1,int r=n) { tree[rt].l=l; tree[rt].r=r; if (l==r) return; int mid=(l+r)>>1; build(lchild); build(rchild); } int lca(int a,int b) { if (deep[a]<deep[b]) swap(a,b); int t=deep[a]-deep[b]; for (int i=0;i<=17;i++) if (t&(1<<i)) a=fa[a][i]; for (int i=17;i>=0;i--) if (fa[a][i]!=fa[b][i]) { a=fa[a][i]; b=fa[b][i]; } if (a==b) return a; else return fa[a][0]; } void modify(int rt,int x,int nu) { int L=tree[rt].l,R=tree[rt].r; int mid=(L+R)>>1; if (L==R) { tree[rt].maxn=tree[rt].sum=nu; return; } if (x<=mid) modify(ln,x,nu); else if (x>mid) modify(rn,x,nu); tree[rt].maxn=max(tree[ln].maxn,tree[rn].maxn); tree[rt].sum=tree[ln].sum+tree[rn].sum; } int query_sum(int rt,int l,int r) { int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1; if (L==l&&R==r) { return tree[rt].sum; } if (l>mid) return query_sum(rn,l,r); else if (r<=mid) return query_sum(ln,l,r); else return query_sum(lchild)+query_sum(rchild); } int query_max(int rt,int l,int r) { int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1; if (L==l&&R==r) { return tree[rt].maxn; } if (l>mid) return query_max(rn,l,r); else if (r<=mid) return query_max(ln,l,r); else return max(query_max(lchild),query_max(rchild)); } int Query_sum(int a,int b) { int ret=0; while (chain[a]!=chain[b]) { ret+=query_sum(1,num[chain[a]],num[a]); a=fa[chain[a]][0]; } ret+=query_sum(1,num[b],num[a]); return ret; } int Query_max(int a,int b) { int ret=-MAXINT; while (chain[a]!=chain[b]) { ret=max(ret,query_max(1,num[chain[a]],num[a])); a=fa[chain[a]][0]; } ret=max(ret,query_max(1,num[b],num[a])); return ret; } int main() { scanf("%d",&n); for (int i=1;i<n;i++) { scanf("%d%d",&u,&v); insert(u,v); insert(v,u); } for (int i=1;i<=n;i++) scanf("%d",&w[i]); scanf("%d",&q); dfs1(1); dfs2(1,1); build(); for (int i=1;i<=n;i++) modify(1,num[i],w[i]); while (q--) { scanf("%s",ch); if (ch[1]=='H') { scanf("%d%d",&a,&b); w[a]=b; modify(1,num[a],b); } else if (ch[1]=='M') { scanf("%d%d",&a,&b); int t=lca(a,b); printf("%d\n",max(Query_max(a,t),Query_max(b,t))); } else if (ch[1]=='S') { scanf("%d%d",&a,&b); int t=lca(a,b); printf("%d\n",Query_sum(a,t)+Query_sum(b,t)-w[t]); } } }
相关文章推荐
- BZOJ 1036 [ZJOI2008]树的统计Count
- bzoj1036 [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count
- [BZOJ]1036: [ZJOI2008]树的统计Count
- 【树链剖分模板】【bzoj1036】: [ZJOI2008]树的统计Count
- BZOJ1036: [ZJOI2008]树的统计Count
- 【BZOJ 1036】【ZJOI 2008】树的统计Count
- Bzoj 1036: [ZJOI2008]树的统计Count
- bzoj 1036: [ZJOI2008]树的统计Count
- bzoj1036[ZJOI2008]树的统计Count
- bzoj1036 [ZJOI2008]树的统计Count
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count 树链剖分
- BZOJ1036: [ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- [BZOJ1036][ZJOI2008]树的统计Count
- BZOJ 树链剖分 1036: [ZJOI2008]树的统计Count
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- BZOJ 1036: [ZJOI2008]树的统计Count
- [BZOJ] 1036: [ZJOI2008]树的统计Count