zoukankan      html  css  js  c++  java
  • BZOJ 3730 震波

    Description

    在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]。
    不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
    接下来你需要在线处理M次操作:
    0 x k 表示发生了一次地震,震中城市为x,影响范围为k,所有与x距离不超过k的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
    1 x y 表示第x个城市的价值变成了y。
    为了体现程序的在线性,操作中的x、y、k都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为0。

    Input

    第一行包含两个正整数N和M。
    第二行包含N个正整数,第i个数表示value[i]。
    接下来N-1行,每行包含两个正整数u、v,表示u和v之间有一条无向边。
    接下来M行,每行包含三个数,表示M次操作。

    Output

    包含若干行,对于每个询问输出一行一个正整数表示答案。

    Sample Input

    8 1
    1 10 100 1000 10000 100000 1000000 10000000
    1 2
    1 3
    2 4
    2 5
    3 6
    3 7
    3 8
    0 3 1

    Sample Output

    11100101

    HINT

    1<=N,M<=100000
    1<=u,v,x<=N
    1<=value[i],y<=10000
    0<=k<=N-1

    先构造出一个动态点分树

    查询时,首先就考虑在当前块内和x距离为k的

    然后还要考虑其他含有x的树根,所以顺着点分树

    然后向上走到i,距离为d

    查询距离树根为k-d的点权和

    这些用线段树以距离为下标实现,每一个根动态开点

    但是还要减去原来子树的,因为不可能走重复的路径

    所以再维护一颗线段树,在往上跳时记录x传递到x上一个根的答案

    查询时减去x传递到上一根的答案就行了

    此题玄学卡常,可以换一种点分写法,这样可以省去get_size操作,快了不少

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 #define MAX 120000
      8 struct Node
      9 {
     10   int next,to;
     11 }edge[MAX<<1];
     12 int num,head[MAX];
     13 int dep[MAX],fa[MAX],pos,size[MAX],minsize,root;
     14 int FA[MAX],son[MAX],top[MAX],Size;
     15 int sum[MAX*150];
     16 int ch[MAX*150][2],RT[MAX<<1],n,m;
     17 int ans,val[MAX];
     18 bool vis[MAX];
     19 inline int gi()
     20 {
     21   int x=0,flag=1;
     22   char ch=getchar();
     23   while (ch<'0'||ch>'9')
     24     {
     25       if (ch=='-') flag=-1;
     26       ch=getchar();
     27     }
     28   while (ch>='0'&&ch<='9')
     29     {
     30       x=(x<<3)+(x<<1)+ch-'0';
     31       ch=getchar();
     32     }
     33   return x*flag;
     34 }
     35 inline void add(int u,int v)
     36 {
     37   num++;
     38   edge[num].next=head[u];
     39   head[u]=num;
     40   edge[num].to=v;
     41 }
     42 void dfs1(int x,int pa)
     43 {
     44   size[x]=1;
     45   dep[x]=dep[pa]+1;
     46   for (int i=head[x];i;i=edge[i].next)
     47     {
     48       int v=edge[i].to;
     49       if (v==pa) continue;
     50       fa[v]=x;
     51       dfs1(v,x);
     52       size[x]+=size[v];
     53       if (size[son[x]]<size[v])
     54       son[x]=v;
     55     }
     56 }
     57 void dfs2(int x,int tp)
     58 {
     59   top[x]=tp;
     60   if (son[x])
     61     dfs2(son[x],tp);
     62   for (int i=head[x];i;i=edge[i].next)
     63     {
     64       int v=edge[i].to;
     65       if (v==fa[x]||v==son[x]) continue;
     66       dfs2(v,v);
     67     }
     68 }
     69 int lca(int x,int y)
     70 {
     71   while (top[x]!=top[y])
     72     {
     73       if (dep[top[x]]<dep[top[y]]) swap(x,y);
     74       x=fa[top[x]];    
     75     }
     76   if (dep[x]<dep[y]) return x;
     77   return y;
     78 }
     79 int dis(int x,int y)
     80 {
     81   return dep[x]+dep[y]-(dep[lca(x,y)]<<1);
     82 }
     83 void get_root(int x,int pa)
     84 {
     85   size[x]=1;
     86   int ret=0;
     87   for (int i=head[x];i;i=edge[i].next)
     88     {
     89       int v=edge[i].to;
     90       if (v==pa||vis[v]) continue;
     91       get_root(v,x);
     92       size[x]+=size[v];
     93       if (size[v]>ret) ret=size[v];
     94     }
     95   if (Size-size[x]>ret) ret=Size-size[x];
     96   if (ret<minsize) minsize=ret,root=x;
     97 }
     98 void solve(int x,int pa)
     99 {
    100   vis[x]=1;
    101   FA[x]=pa;
    102   for (int i=head[x];i;i=edge[i].next)
    103     {
    104       int v=edge[i].to;
    105       if (vis[v]) continue;
    106       minsize=n;Size=size[v];
    107       get_root(v,x);
    108       solve(root,x);
    109     }
    110 }
    111 void update(int &rt,int l,int r,int x,int k)
    112 {
    113   if (!rt) rt=++pos;
    114   sum[rt]+=k;
    115   if (l==r)
    116     return;
    117   int mid=(l+r)>>1;
    118   if (x<=mid) update(ch[rt][0],l,mid,x,k);
    119   else update(ch[rt][1],mid+1,r,x,k);
    120 }
    121 int query(int rt,int l,int r,int L,int R)
    122 {
    123   if (!rt) return 0;
    124   if (l>=L&&r<=R)
    125     return sum[rt];
    126   int mid=(l+r)>>1;
    127   int s=0;
    128   if (L<=mid) s+=query(ch[rt][0],l,mid,L,R);
    129   if (R>mid) s+=query(ch[rt][1],mid+1,r,L,R);
    130   return s;
    131 }
    132 void change(int u,int w)
    133 {
    134   update(RT[u],0,n,0,w);
    135   for (int i=u;FA[i];i=FA[i])
    136     {
    137       int d=dis(u,FA[i]);
    138       update(RT[FA[i]],0,n,d,w);
    139       update(RT[i+n],0,n,d,w);
    140     }
    141 }
    142 void ask(int u,int k)
    143 {
    144   ans+=query(RT[u],0,n,0,k);
    145   for (int i=u;FA[i];i=FA[i])
    146     {
    147       int d=dis(u,FA[i]);
    148       if (d>k) continue;
    149       ans+=query(RT[FA[i]],0,n,0,k-d);
    150       ans-=query(RT[i+n],0,n,0,k-d);
    151     }
    152 }
    153 int main()
    154 {int u,v;
    155   cin>>n>>m;
    156   for (int i=1;i<=n;i++)
    157     val[i]=gi();
    158   for (int i=1;i<=n-1;i++)
    159     {
    160       u=gi();v=gi();
    161       add(u,v);add(v,u);
    162     }
    163   dfs1(1,0);
    164   dfs2(1,1);
    165   minsize=Size=n;
    166   get_root(1,0);
    167   solve(root,0);
    168   for (int i=1;i<=n;i++)
    169     change(i,val[i]);
    170   ans=0;
    171   for (int i=1;i<=m;i++)
    172     {
    173       int opt=gi();
    174       int x=gi(),y=gi();
    175       if (opt==0)
    176     {
    177       x^=ans;y^=ans;
    178       ans=0;
    179       ask(x,y);
    180       printf("%d
    ",ans);
    181     }
    182       else
    183     {
    184       x^=ans;y^=ans;
    185       change(x,y-val[x]);
    186       val[x]=y;
    187     }
    188     }
    189   return 0;
    190 }
  • 相关阅读:
    WPF 常用path示例
    Grid之 Gridlength 解析
    Binding Relative 示例
    Grid之 好玩的GridSplitter
    Blend 制作水晶按钮
    DockPanel—最守规矩布局控件
    万恶之源python介绍
    04.基本数据类型(list,tuple)
    02.万恶之源python 运算符和编码
    基本数据类型(int, bool, str)
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8358147.html
Copyright © 2011-2022 走看看