【BZOJ1036】【ZJOI2008】【树的统计count】【树链剖分】

来源:互联网 发布:阿尔法家家具软件 编辑:程序博客网 时间:2024/04/25 23:22

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”的操作,每行输出一个整数表示要求输出的结果。

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
题解:树链剖分模板题。。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,q,sz,cnt,m;struct use{    int st,en;}b[100001];struct zff{    int maxx,sum;}tree[1000001];int fa[100001][15],size[1000001],deep[100001],point[100001],next[1000001],vis[1000001],pos[1000001],w[1000001],aa,bb;int belong[1000001],ffpos[1000001];char ch[10001];void add(int x,int y){    next[++cnt]=point[x];point[x]=cnt;    b[cnt].st=x;b[cnt].en=y; }void init(){    int a,b;    scanf("%d",&n);    for (int i=1;i<=n-1;i++)    {         scanf("%d%d",&a,&b);         add(a,b);add(b,a);    }   for (int i=1;i<=n;i++)      scanf("%d",&w[i]);}void build(int x,int l,int r){    int mid;    if (l==r){tree[x].maxx=w[ffpos[l]];tree[x].sum=w[ffpos[l]];return;}    mid=(l+r)/2;    build(x*2,l,mid);    build(x*2+1,mid+1,r);    tree[x].maxx=max(tree[x*2].maxx,tree[x*2+1].maxx);    tree[x].sum=tree[x*2].sum+tree[x*2+1].sum; }void dfs(int x){    size[x]=1;vis[x]=1;    for (int i=1;i<=14;i++)     {      if (deep[x]<(1<<i)) break;        fa[x][i]=fa[fa[x][i-1]][i-1];     }    for (int i=point[x];i;i=next[i])      {         if (vis[b[i].en]==1) continue;         deep[b[i].en]=deep[x]+1;         fa[b[i].en][0]=x;         dfs(b[i].en);         size[x]+=size[b[i].en];      }}void dfs2(int x,int c){    int k(0);    pos[x]=++sz;    ffpos[sz]=x;    belong[x]=c;    for (int i=point[x];i;i=next[i]) if (size[b[i].en]>size[k]&&deep[b[i].en]>deep[x]) k=b[i].en;    if (k==0) return;    dfs2(k,c);    for (int i=point[x];i;i=next[i]) if (deep[b[i].en]>deep[x]&&b[i].en!=k) dfs2(b[i].en,b[i].en);}int  lca(int x,int y){    int t;    if(deep[x]<deep[y]) swap(x,y);t=deep[x]-deep[y];    for (int i=0;i<=14;i++) if (t&(1<<i)) x=fa[x][i];     for (int i=14;i>=0;i--)       if (fa[x][i]!=fa[y][i]) {x=fa[x][i];y=fa[y][i];}     if (x==y) return x;else return fa[x][0];}void insert(int k,int l,int r){    int mid;    if(l==r&&l==pos[aa]){tree[k].maxx=w[aa];tree[k].sum=w[aa];return;}    mid=(l+r)/2;    if (pos[aa]<=mid) insert(k*2,l,mid);    else insert(k*2+1,mid+1,r);    tree[k].maxx=max(tree[2*k].maxx,tree[2*k+1].maxx);    tree[k].sum=tree[2*k].sum+tree[2*k+1].sum; }int qsum(int k,int l,int r,int xx,int yy){    int mid,zsum=0;    if (xx<=l&&r<=yy) return tree[k].sum;    mid=(l+r)/2;    if (xx<=mid) zsum+=qsum(k*2,l,mid,xx,yy);    if (yy>mid)  zsum+=qsum(k*2+1,mid+1,r,xx,yy);    return zsum;}int qmax(int k,int l,int r,int xx,int yy){    int mid,zmax=-999999999;    if (xx<=l&&r<=yy)       {        return tree[k].maxx;      }    mid=(l+r)/2;    if (xx<=mid) zmax=max(zmax,qmax(k*2,l,mid,xx,yy));    if (yy>mid)  zmax=max(zmax,qmax(k*2+1,mid+1,r,xx,yy));    return zmax; }int ssum(int x,int y){   int zsum(0);   while (belong[x]!=belong[y])     {        zsum+=qsum(1,1,n,pos[belong[x]],pos[x]);        x=fa[belong[x]][0];     }   zsum+=qsum(1,1,n,pos[y],pos[x]);   return zsum; } int smax(int x,int y){   int zmax(-999999999);   while (belong[x]!=belong[y])     {        zmax=max(zmax,qmax(1,1,n,pos[belong[x]],pos[x]));        x=fa[belong[x]][0];     }   zmax=max(zmax,qmax(1,1,n,pos[y],pos[x]));   return zmax;}void solve(){    int t;    build(1,1,n);    scanf("%d",&m);    for(int i=1;i<=m;i++)     {        scanf("%s%d%d",ch,&aa,&bb);        if (ch[0]=='C'){w[aa]=bb;insert(1,1,n);}        else          {             t=lca(aa,bb);             if (ch[1]=='M') printf("%d\n",max(smax(aa,t),smax(bb,t)));             else printf("%d\n",ssum(aa,t)+ssum(bb,t)-w[t]);               }     }} int main(){    init();    dfs(1);    dfs2(1,1);    solve();}


0 0
原创粉丝点击