zoukankan      html  css  js  c++  java
  • [ZJOI2008]树的统计

    题目描述

    一棵树上有 $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$ 本身。

    输入格式

    输入文件的第一行为一个整数 nn,表示节点的个数。

    接下来 $n1$ 行,每行 2 个整数 a 和 b,表示节点 a 和节点 b 之间有一条边相连。

    接下来一行 n 个整数,第 i个整数 $w_i$ 表示节点 i 的权值。

    接下来 1 行,为一个整数 q,表示操作的总数。

    接下来 q 行,每行一个操作,以 $CHANGE u v$ 或者$ QMAX u v$或者 $QSUM u v$ 的形式给出。

    输出格式

    对于每个 $QMAX$或者 $QSUM$的操作,每行输出一个整数表示要求输出的结果。

    输入输出样例

    输入 
    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
    
    输出 
    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
    

    说明/提示

    对于 $100 \%$的数据,保证 $1le n le 3 imes 10^4$,$0le qle 2 imes 10^5$

    中途操作中保证每个节点的权值 w 在 $-3 imes 10^4$ 到$ 3 imes 10^4$之间。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 int head[100001],tot,n,q,w[100001],d[1000001],fa[1000001],size[1000001],sum,top[1000001],pos[10000001];
      4 struct data {
      5     int to,nxt;
      6 } e[1000001];
      7 struct SegmentTree {
      8     int sum,l,r,mx;
      9 #define l(x) tree[x].l
     10 #define r(x) tree[x].r
     11 #define sum(x) tree[x].sum
     12 #define mx(x) tree[x].mx
     13 } tree[4000004];
     14 void add(int x,int y) {
     15     e[++tot].to=y;
     16     e[tot].nxt=head[x];
     17     head[x]=tot;
     18 }
     19 void build(int p,int l,int r) {
     20     l(p)=l,r(p)=r;
     21     if(l==r)
     22         return;
     23     int mid=l+r>>1;
     24     build(p<<1,l,mid);
     25     build(p<<1|1,mid+1,r);
     26 }
     27 void change(int p,int x,int v) {
     28     if(l(p)==r(p)) {
     29         sum(p)=v;
     30         mx(p)=v;
     31         return;
     32     }
     33     int mid=l(p)+r(p)>>1;
     34     if(x<=mid) change(p<<1,x,v);
     35     else change(p<<1|1,x,v);
     36     mx(p)=max(mx(p<<1),mx(p<<1|1));
     37     sum(p)=sum(p<<1)+sum(p<<1|1);
     38 }
     39 int query_sum(int p,int l,int r) {
     40     if(l<=l(p)&&r>=r(p))
     41         return sum(p);
     42     int val=0;
     43     int mid=l(p)+r(p)>>1;
     44     if(l<=mid) val+=query_sum(p<<1,l,r);
     45     if(r>mid) val+=query_sum(p<<1|1,l,r);
     46     return val;
     47 }
     48 int query_mx(int p,int l,int r) {
     49     if(l<=l(p)&&r>=r(p))
     50         return mx(p);
     51     int val=-(1<<30);
     52     int mid=l(p)+r(p)>>1;
     53     if(l<=mid) val=max(val,query_mx(p<<1,l,r));
     54     if(r>mid) val=max(val,query_mx(p<<1|1,l,r));
     55     return val;
     56 }
     57 void dfs1(int x) {
     58     size[x]=1;
     59     for(int i=head[x]; i; i=e[i].nxt) {
     60         int v=e[i].to;
     61         if(v==fa[x]) continue;
     62         fa[v]=x;
     63         d[v]=d[x]+1;
     64         dfs1(v);
     65         size[x]+=size[v];
     66     }
     67 }
     68 void dfs2(int x,int t) { //jiedian top
     69     int node=0;
     70     pos[x]=++sum;
     71     top[x]=t;
     72     for(int i=head[x]; i; i=e[i].nxt)
     73         if(d[e[i].to]>d[x]&&size[e[i].to]>size[node])
     74             node=e[i].to;
     75     if(node==0)
     76         return;
     77     dfs2(node,t);
     78     for(int i=head[x]; i; i=e[i].nxt)
     79         if(d[e[i].to]>d[x]&&node!=e[i].to)
     80             dfs2(e[i].to,e[i].to);
     81 }
     82 int solve_sum(int x,int y) {
     83     int val=0;
     84     while(top[x]!=top[y]) {
     85         if(d[top[x]]<d[top[y]]) swap(x,y);
     86         val+=query_sum(1,pos[top[x]],pos[x]);
     87         x=fa[top[x]];
     88     }
     89     if(pos[x]>pos[y]) swap(x,y);
     90     val+=query_sum(1,pos[x],pos[y]);
     91     return val;
     92 }
     93 int solve_mx(int x,int y) {
     94     int val=-(1<<30);
     95     while(top[x]!=top[y]) {
     96         if(d[top[x]]<d[top[y]]) swap(x,y);
     97         val=max(val,query_mx(1,pos[top[x]],pos[x]));
     98         x=fa[top[x]];
     99     }
    100     if(pos[x]>pos[y]) swap(x,y);
    101     val=max(val,query_mx(1,pos[x],pos[y]));
    102     return val;
    103 }
    104 void init() {
    105     scanf("%d",&n);
    106     for(int i=1,x,y; i<n; i++)
    107         scanf("%d%d",&x,&y),add(x,y),add(y,x);
    108     for(int i=1; i<=n; i++)
    109         scanf("%d",&w[i]);
    110 }
    111 void solve() {
    112     build(1,1,n);
    113     for(int i=1; i<=n; i++)
    114         change(1,pos[i],w[i]);
    115     scanf("%d",&q);
    116     for(int i=1; i<=q; i++) {
    117         char c[10];
    118         int x,y;
    119         scanf("%s%d%d",c,&x,&y);
    120         if(c[0]=='C')
    121             change(1,pos[x],y);
    122         else {
    123             if(c[1]=='M')
    124                 printf("%d
    ",solve_mx(x,y));
    125             else
    126                 printf("%d
    ",solve_sum(x,y));
    127         }
    128     }
    129 }
    130 int main() {
    131     init();
    132     dfs1(1);
    133     dfs2(1,1);
    134     solve();
    135     return 0;
    136 }
    View Code
  • 相关阅读:
    flex>数据绑定、数据列表 小强斋
    上周问题总结与解决方案
    asp.net 实现无限级分类
    发个项目需求大家瞅瞅
    ASP.NET POST模拟登陆
    HttpWebRequest发送数据 post
    asp.net 生成静态页面
    xcode4.1自带SVN配置
    模拟登录
    C#中用HttpWebRequest/HttpWebResponse来发送/接收数据
  • 原文地址:https://www.cnblogs.com/sbwll/p/13516515.html
Copyright © 2011-2022 走看看