zoukankan      html  css  js  c++  java
  • BZOJ 3531(树链剖分+线段树)

    Problem 旅行 (BZOJ 3531)

    题目大意

      给定一颗树,树上的每个点有两个权值(x,y)。   

      要求维护4种操作:

        操作1:更改某个点的权值x。

        操作2:更改某个点的权值y。

        操作3:求a-->b路径上所有x属性与a,b相同的点y属性的和。

        操作4:求a-->b路径上所有x属性与a,b相同的点y属性的最大值。

      N,Q ,x <= 10^5  ,  y <= 10^4

    解题分析

      由于x属性的范围较大,无法直接统计。

      考虑每次修改为单点修改,询问时只对相同x属性的询问。

      因此,对于每个x属性开一棵线段树,询问时直接在相对应的线段树内查询。

      开这么多棵线段树的话,就要动态开点,某个点的左右儿子的编号不是当前点编号的2倍或2倍加1。

    参考程序

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 #define N 10000008
      8 #define V 100008
      9 #define E 200008
     10 #define lson l,m,ls[rt]
     11 #define rson m+1,r,rs[rt]
     12 
     13 int n,Q,cnt;
     14 int size[V],dep[V],fa[V],son[V],w[V],top[V],rk[V],root[V];
     15 int a[V],c[V];
     16 
     17 struct line{
     18     int u,v,nt;
     19 }eg[E];
     20 int lt[V],sum;
     21 
     22 void adt(int u,int v){
     23     eg[++sum].u=u; eg[sum].v=v; eg[sum].nt=lt[u]; lt[u]=sum;
     24 }
     25 void add(int u,int v){
     26     adt(u,v); adt(v,u);
     27 }
     28 
     29 struct segment_tree{
     30     int sum[N],mx[N],ls[N],rs[N];
     31     void pushup(int rt){
     32         sum[rt]=sum[ls[rt]]+sum[rs[rt]];
     33         mx[rt]=max(mx[ls[rt]],mx[rs[rt]]);    
     34     }
     35     void update(int x,int val,int l,int r,int &rt){   //============ 这个 & 符号用得还是蛮精髓的 ====================
     36         if (rt==0) rt=++cnt;
     37         if (l==r){
     38             sum[rt]=val;
     39             mx[rt]=val;
     40             return;
     41         }
     42         int m=(l+r)/2;
     43         if (x <= m) update(x,val,lson);
     44         if (m <  x) update(x,val,rson);
     45         pushup(rt);
     46     }
     47     int query_sum(int L,int R,int l,int r,int rt){
     48         if (L<=l && r<=R){
     49             return sum[rt];
     50         }
     51         int m=(l+r)/2;
     52         int res=0;
     53         if (L <= m) res+=query_sum(L,R,lson);
     54         if (m <  R) res+=query_sum(L,R,rson);
     55         return res;                      
     56     }
     57     int query_max(int L,int R,int l,int r,int rt){
     58         if (L<=l && r<=R){
     59             return mx[rt];
     60         }
     61         int m=(l+r)/2;
     62         int res=0;
     63         if (L <= m) res=max(res,query_max(L,R,lson));
     64         if (m <  R) res=max(res,query_max(L,R,rson));
     65         return res;                      
     66     }
     67 }T;
     68 
     69 void dfs_1(int u){
     70     dep[u]=dep[fa[u]]+1; size[u]=1; son[u]=0;
     71     for (int i=lt[u];i;i=eg[i].nt){
     72         int v=eg[i].v;
     73         if (v==fa[u]) continue;
     74         fa[v]=u;
     75         dfs_1(v);
     76         size[u]+=size[v];
     77         if (size[v]>size[son[u]]) son[u]=v;
     78     }
     79 }
     80 void dfs_2(int u,int tp){
     81     top[u]=tp; w[u]=++cnt; rk[cnt]=u;
     82     if (son[u]) dfs_2(son[u],tp);
     83     for (int i=lt[u];i;i=eg[i].nt){
     84         int v=eg[i].v;
     85         if (v==fa[u] || v==son[u]) continue;
     86         dfs_2(v,v);
     87     } 
     88 }
     89 void solve_sum(int x,int y){
     90     int res=0,cl=c[x];
     91     while (top[x]!=top[y]){
     92         if (dep[top[x]]<dep[top[y]]) swap(x,y);
     93         res+=T.query_sum(w[top[x]],w[x],1,n,root[cl]);
     94         x=fa[top[x]];
     95     }
     96     if (dep[x]>dep[y]) swap(x,y);
     97     res+=T.query_sum(w[x],w[y],1,n,root[cl]);
     98     printf("%d
    ",res);
     99 }
    100 void solve_max(int x,int y){
    101     int res=0,cl=c[x];
    102     while (top[x]!=top[y]){
    103         if (dep[top[x]]<dep[top[y]]) swap(x,y);
    104         res=max(res,T.query_max(w[top[x]],w[x],1,n,root[cl]));
    105         x=fa[top[x]];
    106     }
    107     if (dep[x]>dep[y]) swap(x,y);
    108     res=max(res,T.query_max(w[x],w[y],1,n,root[cl]));
    109     printf("%d
    ",res);
    110 }
    111 
    112 int main(){
    113     memset(lt,0,sizeof(lt)); sum=1;
    114     scanf("%d %d",&n,&Q);
    115     for (int i=1;i<=n;i++) scanf("%d %d",&a[i],&c[i]);
    116     for (int i=1;i<n;i++){
    117         int u,v;
    118         scanf("%d %d",&u,&v);
    119         add(u,v);
    120     }
    121     dfs_1(1);
    122     dfs_2(1,1);
    123     cnt=0;
    124     for (int i=1;i<=n;i++) T.update(w[i],a[i],1,n,root[c[i]]);
    125     while (Q--){        
    126         char x[5];
    127         int y,z;
    128         scanf("%s%d%d",x,&y,&z);
    129         if (strcmp(x,"CC")==0){
    130             T.update(w[y],0,1,n,root[c[y]]);
    131             c[y]=z;
    132             T.update(w[y],a[y],1,n,root[c[y]]);
    133         }
    134         if (strcmp(x,"CW")==0){
    135             a[y]=z;  // ====================== debug ============//
    136             T.update(w[y],z,1,n,root[c[y]]);
    137         }
    138         if (strcmp(x,"QS")==0){
    139             solve_sum(y,z);
    140         }
    141         if (strcmp(x,"QM")==0){
    142             solve_max(y,z);
    143         }
    144     }
    145 }
    View Code
  • 相关阅读:
    bzoj 1054
    bzoj 1047
    bzoj 2761
    bzoj 1191
    bzoj 2748
    bzoj_1003 物流运输
    新的开始( [USACO08OCT]打井Watering Hole)
    map
    Generic Cow Protests-G——60分做法
    逆序对
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5738901.html
Copyright © 2011-2022 走看看