zoukankan      html  css  js  c++  java
  • 【树链剖分/线段树】BZOJ1036-[ZJOI2008]树的统计Count

    【题目大意】

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

    【思路】

    我来兑现继续做ZJOI2008的flag了。裸的树链剖分,不说什么。但是!主意权值可以为负数,可以为负数!!所以初始化的时候max不是-1,而是要记得清成-INF。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #define lson l,m,rt<<1
      7 #define rson m+1,r,rt<<1|1
      8 using namespace std;
      9 const int MAXN=30000+50;
     10 const int INF=0x7fffffff;
     11 vector<int> E[MAXN];
     12 int fa[MAXN],dep[MAXN],size[MAXN],son[MAXN];
     13 int top[MAXN],pos[MAXN];
     14 int w[MAXN];
     15 int cnt=0,n;
     16 int sum[MAXN<<2],maxn[MAXN<<2];
     17 char str[10];
     18 
     19 /*线段树部分*/
     20 void pushup(int rt)
     21 {
     22     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     23     maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
     24 }
     25 
     26 void modify(int pos,int delta,int l,int r,int rt)
     27 {
     28     if (l==r)
     29     {
     30         sum[rt]=maxn[rt]=delta;
     31         return;
     32     }
     33     int m=(l+r)>>1;
     34     if (pos<=m) modify(pos,delta,lson);
     35     if (pos>m) modify(pos,delta,rson);
     36     pushup(rt);
     37 }
     38 
     39 int query(int sign,int L,int R,int l,int r,int rt)
     40 {
     41     if (L<=l && r<=R)
     42     {
     43         if (sign==1) return sum[rt];else return maxn[rt];
     44     }
     45     int m=(l+r)>>1;
     46     if (sign==1)
     47     {
     48         int ret=0;
     49         if (L<=m) ret+=query(sign,L,R,lson);
     50         if (R>m) ret+=query(sign,L,R,rson);
     51         return ret;
     52     }
     53     else
     54     {
     55         int res=-INF;
     56         if (L<=m) res=max(res,query(sign,L,R,lson));
     57         if (R>m) res=max(res,query(sign,L,R,rson));
     58         return res;
     59     }
     60 }
     61 
     62 /*树链剖分部分*/
     63 void addedge(int u,int v)
     64 {
     65     E[u].push_back(v);
     66     E[v].push_back(u);
     67 }
     68 
     69 void dfs1(int u,int pre,int d)
     70 {
     71     fa[u]=pre;
     72     dep[u]=d;
     73     size[u]=1;
     74     int tmpmax=0,hson=-1;
     75     for (int i=0;i<E[u].size();i++)
     76     {
     77         int to=E[u][i];
     78         if (to==pre) continue;
     79         dfs1(to,u,d+1);
     80         if (size[to]>tmpmax)
     81         {
     82             tmpmax=size[to];
     83             hson=to;
     84         }
     85         size[u]+=size[to];
     86     }
     87     son[u]=hson;
     88 }
     89 
     90 void dfs2(int u,int t)
     91 {
     92     pos[u]=++cnt;
     93     top[u]=t;
     94     if (son[u]==-1) return;
     95     dfs2(son[u],t);
     96     for (int i=0;i<E[u].size();i++)
     97         if (E[u][i]!=son[u] && E[u][i]!=fa[u]) dfs2(E[u][i],E[u][i]);
     98 }
     99 
    100 int Que(int sign,int u,int v)
    101 {
    102     int ans;
    103     if (sign==1) ans=0;else ans=-INF;
    104     int f1=top[u],f2=top[v];
    105     while (f1!=f2)
    106     {
    107         if (dep[f1]<dep[f2])
    108         {
    109             swap(f1,f2);
    110             swap(u,v);
    111         }
    112         if (sign==1) ans+=query(1,pos[f1],pos[u],1,n,1);
    113             else ans=max(ans,query(2,pos[f1],pos[u],1,n,1));
    114         u=fa[f1];
    115         f1=top[u];
    116     }
    117     if (dep[u]>dep[v]) swap(u,v);
    118     if (sign==1) ans+=query(1,pos[u],pos[v],1,n,1);
    119             else ans=max(ans,query(2,pos[u],pos[v],1,n,1));
    120     return ans;
    121 }
    122 
    123 /*主程序部分*/ 
    124 void init()
    125 {
    126     scanf("%d",&n);
    127     for (int i=0;i<n-1;i++)
    128     {
    129         int a,b;
    130         scanf("%d%d",&a,&b);
    131         addedge(a,b);
    132     }
    133     dfs1(1,0,1);
    134     dfs2(1,1);
    135 } 
    136 
    137 void get_ans()
    138 {
    139     for (int i=1;i<=n;i++) 
    140     {
    141         scanf("%d",&w[i]);
    142         modify(pos[i],w[i],1,n,1);
    143     }
    144     int q;
    145     scanf("%d",&q); 
    146     for (int i=0;i<q;i++)
    147     {
    148         int u,v;
    149         scanf("%s%d%d",str,&u,&v);
    150         if (str[0]=='C') modify(pos[u],v,1,n,1);
    151         if (str[0]=='Q' && str[1]=='S') cout<<Que(1,u,v)<<endl;
    152         if (str[0]=='Q' && str[1]=='M') cout<<Que(2,u,v)<<endl;
    153     }
    154 }
    155 
    156 int main()
    157 {
    158     init();
    159     get_ans();
    160     return 0;
    161 }
  • 相关阅读:
    备忘录模式
    观察者模式
    状态模式
    模板方法模式
    策略模式
    装饰者模式
    访问者模式
    工作那些事(二十七)项目经理在项目中是什么角色?
    工作那些事(二十六)个人和团队
    工作那些事(二十五)项目经理与产品经理
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5617387.html
Copyright © 2011-2022 走看看