• HYSBZ 1036树链剖分


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

    Hint

     树链剖分+线段树模板题:

    参考代码:

      1 //树链剖分+线段树 
      2 /*
      3  I. CHANGE u t : 把结点u的权值改为t 
      4 II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
      5 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 (包括u和v本身)
      6 */ 
      7 #include<bits/stdc++.h>
      8 using namespace std;
      9 #define mem(a,b) memset(a,b,sizeof a)
     10 #define mp make_pair
     11 #define eps 1e-8
     12 #define lson l,mid,rt<<1
     13 #define rson mid+1,r,rt<<1|1
     14 typedef long long ll;
     15 typedef unsigned long long ull; 
     16 const int INF=0x3f3f3f3f;
     17 const ll inf=0x3f3f3f3f3f3f3f3fll;
     18 const int maxn=2e5+10;
     19 int siz[maxn],top[maxn],fa[maxn],dep[maxn];
     20 int tid[maxn],rnk[maxn],son[maxn],cnt;
     21 int head[maxn],tot,a[maxn];
     22 
     23 struct Node{
     24     int v,nxt;
     25 } edge[maxn];
     26 
     27 struct Tree{
     28     int l,r,sz;
     29     int sum,max_num;
     30 } tree[maxn<<2];
     31 
     32 void Init()
     33 {
     34     tot=cnt=0;
     35     mem(head,-1); mem(son,-1);
     36     mem(siz,0); mem(top,0);
     37 }
     38 
     39 
     40 void Pushup(int pos)
     41 {
     42     tree[pos].max_num=max(tree[pos<<1].max_num,tree[pos<<1|1].max_num);
     43     tree[pos].sum=tree[pos<<1].sum+tree[pos<<1|1].sum;
     44 }
     45 
     46 void Build(int l,int r,int rt)
     47 {
     48     tree[rt].l=l;tree[rt].r=r;tree[rt].sz=r-l+1;
     49     if(l==r)
     50     {
     51         tree[rt].max_num=tree[rt].sum=a[rnk[l]];
     52         return ;
     53     }
     54     int mid=(l+r)>>1;
     55     Build(lson); Build(rson);
     56     Pushup(rt);
     57 }
     58 
     59 void Update(int pos,int c,int l,int r,int rt)
     60 {
     61     if(l==r)
     62     {
     63         tree[rt].max_num=tree[rt].sum=c;
     64         return ;
     65     }
     66     int mid=(l+r)>>1;
     67     if(pos<=mid) Update(pos,c,lson);
     68     else Update(pos,c,rson);
     69     Pushup(rt);
     70 }
     71 
     72 int Query_sum(int L,int R,int l,int r,int rt)//求L~R的和 
     73 {
     74     if(l>=L && r<=R) return tree[rt].sum;
     75     int mid=(l+r)>>1;
     76     int ans=0;
     77     if(L<=mid) ans+=Query_sum(L,R,lson);
     78     if(R>mid) ans+=Query_sum(L,R,rson);
     79     return ans;
     80 }
     81 
     82 int Query_max(int L,int R,int l,int r,int rt)//寻找L~R的最大值 
     83 {
     84     if(L<=l && r<=R) return tree[rt].max_num;
     85     int mid=(l+r)>>1;
     86     int ans=-INF;
     87     if(L<=mid) ans=max(ans,Query_max(L,R,lson));
     88     if(R>mid) ans=max(ans,Query_max(L,R,rson));
     89     return ans;
     90 }
     91 
     92 void addedge(int u,int v)
     93 {
     94     edge[tot].v=v;
     95     edge[tot].nxt=head[u];
     96     head[u]=tot++;
     97 }
     98 
     99 void dfs1(int u,int father,int depth)
    100 {
    101     fa[u]=father;
    102     dep[u]=depth;
    103     siz[u]=1;
    104     for(int i=head[u];~i;i=edge[i].nxt)
    105     {
    106         int v=edge[i].v;
    107         if(v!=fa[u])
    108         {
    109             dfs1(v,u,depth+1);
    110             siz[u]+=siz[v];
    111             if(son[u]==-1 || siz[v]>siz[son[u]]) son[u]=v;
    112          } 
    113     }
    114 }
    115 
    116 void dfs2(int u,int t)
    117 {
    118     top[u]=t;
    119     tid[u]=++cnt; rnk[cnt]=u;//tid[]:表示该点在线段树中的位置/:rnk[]:和tid[]数组相反,根据线段树中的位置,找到树中位置 
    120     if(son[u]==-1) return ;
    121     dfs2(son[u],t);
    122     for(int i=head[u];~i;i=edge[i].nxt)
    123     {
    124         int v=edge[i].v;
    125         if(v!=son[u] && v!=fa[u]) dfs2(v,v);
    126     }    
    127 }
    128 
    129 int LCA(int u,int v,int flag)//沿着树链求LCA(根据flag的不同,求不同的值) 
    130 {
    131     int fu=top[u],fv=top[v],res;
    132     if(flag) res=-INF;// flag=1 求最大值 
    133     else res=0; //flag=0 求和 
    134     while(fu!=fv)
    135     {
    136         if(dep[fu]<dep[fv]) swap(fu,fv),swap(u,v);
    137         if(flag) res=max(res,Query_max(tid[fu],tid[u],1,cnt,1));
    138         else res+=Query_sum(tid[fu],tid[u],1,cnt,1);
    139         u=fa[fu],fu=top[u]; 
    140     }
    141     if(dep[u]>dep[v]) swap(u,v);
    142     if(flag) res=max(res,Query_max(tid[u],tid[v],1,cnt,1));
    143     else res+=Query_sum(tid[u],tid[v],1,cnt,1);
    144     return res;
    145 }
    146 
    147 int main()
    148 {
    149     int n,t,u,v,w;
    150     char op[10];
    151     while(~scanf("%d",&n))
    152     {
    153         Init();
    154         for(int i=1;i<n;i++)
    155         {
    156             scanf("%d%d",&u,&v);
    157             addedge(u,v);
    158             addedge(v,u);
    159         }
    160         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    161         dfs1(1,0,0);
    162         dfs2(1,1);
    163         Build(1,cnt,1);
    164         scanf("%d",&t);
    165         while(t--)
    166         {
    167             scanf("%s",op);
    168             scanf("%d%d",&u,&v);
    169             if(op[1]=='S') printf("%d
    ",LCA(u,v,0));
    170             else if(op[1]=='M') printf("%d
    ",LCA(u,v,1));
    171             else Update(tid[u],v,1,cnt,1);
    172         }
    173     }
    174     return 0;
    175 }
    176   
    View Code
  • 相关阅读:
    概率论中几个入门公式
    记一道贝叶斯公式的裸题
    BZOJ3585: mex(主席树)
    利用MingW检验程序运行内存
    清北集训Day3T1(转换)
    万能pb_ds头文件—bits/extc++.h
    清北集训Day1T3 LYK loves jumping(期望DP)
    洛谷P1962 斐波那契数列(矩阵快速幂)
    namespace用法
    BZOJ4868: [Shoi2017]期末考试
  • 原文地址:https://www.cnblogs.com/csushl/p/9704379.html
Copyright © 2020-2023  润新知