zoukankan      html  css  js  c++  java
  • [bzoj4765]普通计算姬(分块+树状数组+DFS序)

    题意

    给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权值和。
    计算姬支持下列两种操作:  1 给定两个整数u,v,修改点u的权值为v。  2 给定两个整数l,r,计算sum[l]+sum[l+1]+….+sum[r-1]+sum[r]
    N<=10^5,M<=10^5

    题解

    每一个块中统计sum[i]的和,这个直接求出DFS序维护树状数组nlogn统计就行。

    然后询问时对于一个整块直接加上我们统计的sum[i]的和,然后对于边角余料,我们用树状数组求就行。

    修改时我们要维护树状数组直接位置上加(x-v[i])就行。

    然后我们要维护块的和,就需要把和加上块中i的祖先数(包含i)*(x-v[i])。

    所以我们预处理出f[i][j]代表第i块中j(包括j)的祖先数。这个dfs中用一个数组记录祖先情况(进入时加上自己,推出时减掉自己),对于每个点扫一遍每个块统计就行。

    然后这题要用unsigned long long 然后也不能全开,会MLE

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<algorithm>
      6 using namespace std;
      7 const int  N=100100;
      8 int  cnt,head[N];
      9 int  size[N],id[N],tot;
     10 int  num[400],block[N],f[400][N];
     11 unsigned long long sum[400],a[N],tr[N],ans,v[N];
     12 int  n,m,R[400],L[400],Block,root;
     13 struct edge{
     14     int  to,nxt;
     15 }e[N*2];
     16 void add(int  u,int  v){
     17     cnt++;
     18     e[cnt].nxt=head[u];
     19     e[cnt].to=v;
     20     head[u]=cnt;
     21 }
     22 void dfs1(int  u,int  fa){
     23     size[u]=1;
     24     id[u]=++tot;
     25     for(int  i=head[u];i;i=e[i].nxt){
     26         int  v=e[i].to;
     27         if(v==fa)continue;
     28         dfs1(v,u);
     29         size[u]+=size[v];
     30     }
     31 }
     32 void dfs2(int  u,int  fa){
     33     num[block[u]]++;
     34     for(int  i=1;i<=block[n];i++){
     35         f[i][u]+=num[i];
     36     }
     37     for(int  i=head[u];i;i=e[i].nxt){
     38         int  v=e[i].to;
     39         if(v==fa)continue;
     40         dfs2(v,u);
     41     }
     42     num[block[u]]--;
     43 }
     44 int  lowbit(int  x){
     45     return x&-x;
     46 }
     47 void update(int  x,unsigned long long w){
     48     for(int  i=x;i<=n;i+=lowbit(i)){
     49         tr[i]+=w;
     50     }
     51 }
     52 unsigned long long query(int  x){
     53     unsigned long long tmp=0;
     54     for(int  i=x;i;i-=lowbit(i)){
     55         tmp+=tr[i];
     56     }
     57     return tmp;
     58 }
     59 int main(){
     60     scanf("%d%d",&n,&m);
     61     for(int  i=1;i<=n;i++){
     62         scanf("%llu",&v[i]);
     63     }
     64     for(int  i=1;i<=n;i++){
     65         int  u,v;
     66         scanf("%d%d",&u,&v);
     67         if(u==0){
     68             root=v;
     69             continue;
     70         }
     71         add(u,v);
     72         add(v,u);
     73     }
     74     dfs1(root,0);
     75     for(int  i=1;i<=n;i++){
     76         update(id[i],v[i]);
     77     }
     78     for(int  i=1;i<=n;i++){
     79         a[i]=query(id[i]+size[i]-1)-query(id[i]-1);
     80     //    cout<<i<<" "<<id[i]<<" "<<size[i]<<" "<<a[i]<<endl;
     81     }
     82     Block=sqrt(n);
     83     for(int  i=1;i<=n;i++){
     84         block[i]=(i-1)/Block+1;
     85         sum[block[i]]+=a[i];
     86         if(!L[block[i]])L[block[i]]=i;
     87         R[block[i]]=i;
     88     }
     89     dfs2(root,0);
     90     while(m--){
     91         int  k,x,y;
     92         scanf("%d%d%d",&k,&x,&y);
     93         if(k==1){
     94             for(int  i=1;i<=block[n];i++){
     95                 sum[i]+=f[i][x]*(y-v[x]);
     96             }
     97             update(id[x],y-v[x]);
     98             v[x]=y;
     99         }
    100         else{
    101             ans=0;
    102             if(block[x]+1>=block[y]){
    103                 for(int  i=x;i<=y;i++){
    104                     ans+=query(id[i]+size[i]-1)-query(id[i]-1);
    105                 }
    106             }
    107             else{
    108                 for(int  i=block[x]+1;i<=block[y]-1;i++){
    109                     ans+=sum[i];
    110                 }
    111                 for(int  i=x;i<=R[block[x]];i++){
    112                     ans+=query(id[i]+size[i]-1)-query(id[i]-1);
    113                 }
    114                 for(int  i=L[block[y]];i<=y;i++){
    115                     ans+=query(id[i]+size[i]-1)-query(id[i]-1);
    116                 }
    117             }
    118             printf("%llu
    ",ans);
    119         }
    120     }
    121     return 0;
    122 }
  • 相关阅读:
    【STM32】串行通信原理
    【STM32】NVIC中断优先级管理
    【Linux-驱动】RTC设备驱动架构
    【Linux-驱动】在sysfs下创建对应的class节点---class_create
    【Linux-驱动】将cdev加入到系统中去---cdev_add
    【Linux-驱动】简单字符设备驱动结构和初始化
    【Linux-驱动】printk的打印级别
    【Linux 网络编程】REUSADDR
    【Linux 网络编程】常用TCP/IP网络编程函数
    linux定时重启tomcat脚本
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9487877.html
Copyright © 2011-2022 走看看