bzoj 1036: [ZJOI2008]树的统计Count
2017-04-19 19:27
309 查看
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 16200 Solved: 6612
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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”的操作,每行输出一个整数表示要求输出的结果。
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
【分析】
忘记设置初始值WA了好几次2333….
【代码】
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 16200 Solved: 6612
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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”的操作,每行输出一个整数表示要求输出的结果。
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
【分析】
忘记设置初始值WA了好几次2333….
【代码】
//bzoj #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define inf 1e9+7 #define M(a) memset(a,0,sizeof a) #define fo(i,j,k) for(i=j;i<=k;++i) using namespace std; const int mxn=300005; int n,m,tot,cnt; int head[mxn],w[mxn],pos[mxn]; struct edge {int to,next;} f[mxn<<1]; struct tree { int fa,son,s,e,top,sz,dep; }e[mxn]; struct line { int l,r,mx,sum; }t[mxn<<2]; inline void add(int u,int v) { f[++cnt].to=v,f[cnt].next=head[u],head[u]=cnt; } inline void dfs1(int u) { e[u].sz=1; for(int i=head[u];i;i=f[i].next) { int v=f[i].to; if(v==e[u].fa) continue; e[v].fa=u; e[v].dep=e[u].dep+1; dfs1(v); e[u].sz+=e[v].sz; if(e[v].sz>e[e[u].son].sz) e[u].son=v; } } inline void dfs2(int u,int top) { e[u].top=top; e[u].s=++tot; pos[tot]=u; if(e[u].son) { dfs2(e[u].son,top); for(int i=head[u];i;i=f[i].next) { int v=f[i].to; if(v!=e[u].fa && v!=e[u].son) dfs2(v,v); } } e[u].e=tot; } inline void update(int num) { t[num].mx=max(t[num<<1].mx,t[num<<1|1].mx); t[num].sum=t[num<<1].sum+t[num<<1|1].sum; } inline void build(int num,int l,int r) { t[num].l=l,t[num].r=r; if(l==r) { t[num].mx=t[num].sum=w[pos[l]]; return; } int mid=l+r>>1; build(num<<1,l,mid); build(num<<1|1,mid+1,r); update(num); } inline void change(int num,int L,int R,int c) { if(L<=t[num].l && t[num].r<=R) { t[num].mx=t[num].sum=c; return; } if(L<=t[num<<1].r) change(num<<1,L,R,c); if(R>=t[num<<1|1].l) change(num<<1|1,L,R,c); update(num); } inline int Qsum(int num,int L,int R) { if(L<=t[num].l && t[num].r<=R) return t[num].sum; int ans=0; if(L<=t[num<<1].r) ans+=Qsum(num<<1,L,R); if(R>=t[num<<1|1].l) ans+=Qsum(num<<1|1,L,R); return ans; } inline int Qmax(int num,int L,int R) { if(L<=t[num].l && t[num].r<=R) return t[num].mx; int mx=-inf; if(L<=t[num<<1].r) mx=max(mx,Qmax(num<<1,L,R)); if(R>=t[num<<1|1].l) mx=max(mx,Qmax(num<<1|1,L,R)); return mx; } inline int Fsum(int x,int y) { int ans=0; int f1=e[x].top,f2=e[y].top; while(f1!=f2) { if(e[f1].dep<e[f2].dep) swap(x,y),swap(f1,f2); ans+=Qsum(1,e[f1].s,e[x].s); x=e[f1].fa; f1=e[x].top; } if(e[x].dep<e[y].dep) ans+=Qsum(1,e[x].s,e[y].s); else ans+=Qsum(1,e[y].s,e[x].s); return ans; } inline int Fmax(int x,int y) { int ans=-inf; int f1=e[x].top,f2=e[y].top; while(f1!=f2) { if(e[f1].dep<e[f2].dep) swap(x,y),swap(f1,f2); ans=max(ans,Qmax(1,e[f1].s,e[x].s)); x=e[f1].fa; f1=e[x].top; } if(e[x].dep<e[y].dep) ans=max(ans,Qmax(1,e[x].s,e[y].s)); else ans=max(ans,Qmax(1,e[y].s,e[x].s)); return ans; } int main() { // freopen("bzoj_1036.in","r",stdin); // freopen("bzoj_1036.out","w",stdout); int i,j,u,v,x,y; scanf("%d",&n); fo(i,2,n) { scanf("%d%d",&u,&v); add(u,v),add(v,u); } fo(i,1,n) scanf("%d",&w[i]); dfs1(1); dfs2(1,1); build(1,1,n); scanf("%d",&m); while(m--) { char opt[10]; scanf("%s",opt); scanf("%d%d",&u,&v); if(opt[0]=='C') change(1,e[u].s,e[u].s,v); else if(opt[1]=='S') printf("%d\n",Fsum(u,v)); else printf("%d\n",Fmax(u,v)); } return 0; }
相关文章推荐
- 【BZOJ 1036】[ZJOI2008]树的统计Count
- bzoj 1036 [ZJOI2008]树的统计Count (树链剖分 + 线段树)
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
- bzoj1036 [ZJOI2008]树的统计Count (树链剖分|Link Cut Tree)
- BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分裸题)
- BZOJ 1036: [ZJOI2008]树的统计Count
- [ZJOI2008]树的统计Count bzoj1036 树链剖分
- BZOJ 1036: [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千题计划124:bzoj1036: [ZJOI2008]树的统计Count
- BZOJ-1036: [ZJOI2008]树的统计Count (树链剖分 线段树 单点修改 区间查询 入门题)
- AC日记——[ZJOI2008]树的统计Count bzoj 1036
- BZOJ 1036: [ZJOI2008]树的统计Count
- _bzoj1036 [ZJOI2008]树的统计Count【树链剖分】
- 【BZOJ】1036 [ZJOI2008]树的统计Count 树链剖分+线段树