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
  • 相关阅读:
    环境是如何建立的 启动文件有什么
    环境中存储的是什么
    串行 并行 异步 同步
    TPC-H is a Decision Support Benchmark
    进程通信类型 管道是Linux支持的最初Unix IPC形式之一 命名管道 匿名管道
    删除环境变量
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5738901.html
Copyright © 2011-2022 走看看