震波
震波
在一片土地上有 $N$ 個城市,通過 $N-1$ 條無向邊互相連接,形成一棵樹的結構,相鄰兩個城市的距離為 $1$,其中第 $i$ 個城市的價值為 $value[i]$。不幸的是,這片土地常常發生地震,并且隨著時代的發展,城市的價值也往往會發生變動。 接下來你需要在線處理 $M$ 次操作:
- $0~x~k$ 表示發生了一次地震,震中城市為 $x$ ,影響范圍為 $k$ ,所有與 $x$ 距離不超過 $k$ 的城市都將受到影響,該次地震造成的經濟損失為所有受影響城市的價值和。
- $1~x~y$ 表示第$x$個城市的價值變成了 $y$ 。 為了體現程序的在線性,操作中的 $x$ 、$y$ 、$k$ 都需要異或你程序上一次的輸出來解密,如果之前沒有輸出,則默認上一次的輸出為 $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 @ 2019-04-05 08:23 liankewei123456 閱讀( ...) 評論( ...) 編輯 收藏
總結
- 上一篇: 网站优化SEO包括哪些方面
- 下一篇: Android Hook之Frida安装