震波

在一片土地上有 N 个城市,通过 N1 条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为 1,其中第 i 个城市的价值为 value[i]
不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的价值也往往会发生变动。
接下来你需要在线处理 M 次操作:
- 0 x k 表示发生了一次地震,震中城市为 x ,影响范围为 k ,所有与 x 距离不超过 k 的城市都将受到影响,该次地震造成的经济损失为所有受影响城市的价值和。
- 1 x y 表示第x个城市的价值变成了 y
为了体现程序的在线性,操作中的 xyk 都需要异或你程序上一次的输出来解密,如果之前没有输出,则默认上一次的输出为 0
 
 
 
 
Solution
考虑建出点分树,每一个点开一棵以长度为下标的线段树。
查询时可以一步步往上跳。假设他到父亲的权值为t,每此查询与x距离为k k+t ...的点。
可是这样会算重。
那么可以在每个点再开一棵线段树,下标为点到他点分树上父亲的权值。
每次减去第二棵线段树中k+t的值。也就是自己与父亲相同的贡献
卡常毒题
orz邵神树状数组常树优秀
 
复制代码
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<cmath>
  7 #define maxn 200006
  8 using namespace std;
  9 int n,m,head[maxn],a[maxn],val[maxn],siz,tot,deep[maxn];
 10 int f[maxn],vis[maxn],par[maxn],sz[maxn],rt;
 11 int cnt,root[maxn],st[maxn][20],sc,dfn[maxn],l2[maxn];
 12 struct node{
 13     int v,nex;
 14 }e[maxn];
 15 struct no{
 16     int ls,rs,v;
 17 }tr[maxn*140];
 18 inline void lca(int k,int fa){
 19     st[dfn[k]=++sc][0]=deep[k]=deep[fa]+1;
 20     for(int i=head[k];i;i=e[i].nex)if(e[i].v!=fa)lca(e[i].v,k),st[++sc][0]=deep[k];
 21 }
 22 inline void add(int &k,int l,int r,int pl,int v){
 23     if(!k)k=++cnt;
 24     if(l==r){tr[k].v+=v;return;}
 25     int mid=l+r>>1;
 26     if(pl<=mid)add(tr[k].ls,l,mid,pl,v);
 27     else add(tr[k].rs,mid+1,r,pl,v);
 28     tr[k].v=tr[tr[k].ls].v+tr[tr[k].rs].v;
 29 }
 30 inline int ask(int k,int l,int r,int pl){
 31     if(!k||pl<0)return 0;
 32     if(l==r)return tr[k].v;
 33     int mid=l+r>>1;
 34     if(pl<=mid)return ask(tr[k].ls,l,mid,pl);
 35     else return tr[tr[k].ls].v+ask(tr[k].rs,mid+1,r,pl);
 36     
 37 }
 38 inline int dis(int x,int y){
 39     if(dfn[y]<dfn[x])swap(x,y);
 40     int i=l2[dfn[y]-dfn[x]+1];
 41     int dl=min(st[dfn[x]][i],st[dfn[y]-(1<<i)+1][i]);
 42     return deep[x]+deep[y]-(dl<<1);
 43 }
 44 inline void dfs(int o,int la,int k,int fa){
 45     add(root[o],0,n,dis(o,k),val[k]);
 46     if(la)add(root[o+n],0,n,dis(k,la),val[k]);
 47     sz[k]=1;
 48     for(int i=head[k];i;i=e[i].nex){
 49         if(e[i].v==fa||vis[e[i].v])continue;
 50         dfs(o,la,e[i].v,k);
 51         sz[k]+=sz[e[i].v];
 52     }
 53 }
 54 inline void findr(int k,int fa){
 55     sz[k]=1;f[k]=0;
 56     for(int i=head[k];i;i=e[i].nex){
 57         if(e[i].v==fa||vis[e[i].v])continue;
 58         findr(e[i].v,k);
 59         sz[k]+=sz[e[i].v];
 60         f[k]=max(f[k],sz[e[i].v]);
 61     }
 62     f[k]=max(f[k],siz-sz[k]);
 63     if(f[k]<f[rt])rt=k;
 64 }
 65 inline void work(int k,int la){
 66     vis[k]=1;
 67     dfs(k,la,k,0);
 68     for(int i=head[k];i;i=e[i].nex){
 69         if(!vis[e[i].v]){
 70             siz=sz[e[i].v];rt=0;findr(e[i].v,k);
 71             par[rt]=k;
 72             work(rt,k);
 73         }
 74     }
 75 }
 76 inline int R(){
 77     int v=0;char ch;
 78     while(!isdigit(ch=getchar()));v=ch-48;
 79     while(isdigit(ch=getchar()))v=(v<<1)+(v<<3)+ch-48;
 80     return v;
 81 }
 82 int main()
 83 {
 84     n=R();m=R();
 85     for(int i=1;i<=n;i++)val[i]=R();
 86     for(int i=1,t1,t2;i<n;i++){
 87         t1=R();t2=R();
 88         e[++tot].v=t2;e[tot].nex=head[t1];head[t1]=tot;
 89         e[++tot].v=t1;e[tot].nex=head[t2];head[t2]=tot;
 90     }
 91     lca(1,0);
 92     for(int i=2;i<=sc;i++)l2[i]=l2[i/2]+1;
 93     for(int j=1;j<=l2[sc];j++)
 94         for(int i=1;i+(1<<j)<=sc+1;i++)st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);
 95     rt=0;f[0]=1e9;siz=n;findr(1,0);
 96     work(rt,0);
 97     int ans=0;
 98     for(int i=1,op,y,x,k;i<=m;i++){
 99         op=R();
100         if(op==0){
101             x=R();k=R();
102             x^=ans,k^=ans;
103             ans=0;int fi=x;
104             for(int d=0;x;){
105                 ans+=ask(root[x],0,n,k-d);d=dis(par[x],fi);
106                 if(par[x])ans-=ask(root[n+x],0,n,k-d);
107                 x=par[x];
108             }
109             printf("%d\n",ans);
110         }
111         if(op==1){
112             x=R();y=R();
113             x^=ans;y^=ans;
114             int fi=x;
115             for(int d=0;x;){
116                 add(root[x],0,n,d,y-val[fi]);d=dis(fi,par[x]);
117                 if(par[x])add(root[n+x],0,n,d,y-val[fi]);
118                 x=par[x];
119             }
120             val[fi]=y;
121         }
122     }
123     return 0;
124 }
View Code
复制代码

 

 

posted @   liankewei123456  阅读(312)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示