您的位置:首页 > 其它

bzoj千题计划124:bzoj1036: [ZJOI2008]树的统计Count

2017-11-28 21:56 465 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=1036

树链剖分板子题

#include<cstdio>
#include<iostream>
#include<algorithm>

#define N 30001

using namespace std;

int front
,to[N<<1],nxt[N<<1],tot;

int n,val
;

int siz
,fa
,dep
;

int id
,dy
,bl
;

int mx[N<<2],sum[N<<2];

int ans;

void read(int &x)
{
x=0; int f=1; char c=getchar();
while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); }
while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
x*=f;
}

void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
}

void dfs1(int x,int y)
{
siz[x]=1;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=y)
{
dep[to[i]]=dep[x]+1;
fa[to[i]]=x;
dfs1(to[i],x);
siz[x]+=siz[to[i]];
}
}

void dfs2(int x,int top)
{
bl[x]=top;
id[x]=++tot; dy[tot]=x;
int y=0;
for(int i=front[x];i;i=nxt[i])
{
if(to[i]==fa[x]) continue;
if(siz[to[i]]>siz[y]) y=to[i];
}
if(y) dfs2(y,top);
for(int i=front[x];i;i=nxt[i])
{
if(to[i]==fa[x] || to[i]==y) continue;
dfs2(to[i],to[i]);
}
}

void build(int k,int l,int r)
{
if(l==r)
{
mx[k]=sum[k]=val[dy[l]];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
mx[k]=max(mx[k<<1],mx[k<<1|1]);
sum[k]=sum[k<<1]+sum[k<<1|1];
}

void change(int k,int l,int r,int pos,int w)
{
if(l==r)
{
mx[k]=sum[k]=w;
return;
}
int mid=l+r>>1;
if(pos<=mid) change(k<<1,l,mid,pos,w);
else change(k<<1|1,mid+1,r,pos,w);
mx[k]=max(mx[k<<1],mx[k<<1|1]);
sum[k]=sum[k<<1]+sum[k<<1|1];
}

void query(int k,int l,int r,int opl,int opr,bool ty)
{
if(l>=opl && r<=opr)
{
if(!ty) ans=max(ans,mx[k]);
else ans+=sum[k];
return;
}
int mid=l+r>>1;
if(opl<=mid) query(k<<1,l,mid,opl,opr,ty);
if(opr>mid) query(k<<1|1,mid+1,r,opl,opr,ty);
}

void solve(int u,int v,bool ty)
{
if(!ty) ans=-1e7;
else ans=0;
while(bl[u]!=bl[v])
{
if(dep[bl[u]]<dep[bl[v]]) swap(u,v);
query(1,1,n,id[bl[u]],id[u],ty);
u=fa[bl[u]];
}
if(dep[u]>dep[v]) swap(u,v);
query(1,1,n,id[u],id[v],ty);
cout<<ans<<'\n';
}

int main()
{
int u,v;  read(n);
for(int i=1;i<n;++i) read(u),read(v),add(u,v);
for(int i=1;i<=n;++i) read(val[i]);
dfs1(1,0); tot=0; dfs2(1,1);
build(1,1,n);
int m; char c[7];  read(m);
while(m--)
{
scanf("%s",c);
read(u); read(v);
if(c[0]=='C') change(1,1,n,id[u],v);
else if(c[1]=='M')  solve(u,v,0);
else solve(u,v,1);
}
}


1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 19421 Solved: 7912
[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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: