BZOJ3221 [Codechef FEB13] Obserbing the tree树上询问

来源:互联网 发布:香蕉网络电视手机版 编辑:程序博客网 时间:2024/06/11 20:36

闲来无事水一发毒瘤题

链剖+主席树即可

区间加一个等差数列标记合并的时候把首项和公差都加起来就好了

因为区间修改所以要标记永久化,除了标记以外还要记录子树内因更改所增加的和

#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<algorithm>#include<iomanip>#include<vector>#include<stack>#include<queue>#include<map>#include<set>#include<bitset>using namespace std;#define MAXN 100010#define MAXM 20000010#define ll long long#define INF 1000000000#define MOD 1000000007#define eps 1e-8struct vec{int to;int fro;};vec mp[MAXN*2];int tai[MAXN],cnt;int rt[MAXN];ll sum[MAXM],st[MAXM],c[MAXM];int son[MAXM][2];int fa[MAXN],Son[MAXN],tp[MAXN],dfn[MAXN],dep[MAXN],siz[MAXN],tim;int tot;int TOT;int now;int n,m;ll la;inline void be(int x,int y){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;}inline void bde(int x,int y){be(x,y);be(y,x);}void dfs1(int x){int i,y;siz[x]=1;dep[x]=dep[fa[x]]+1;for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if(!siz[y]){fa[y]=x;dfs1(y);siz[x]+=siz[y];if(siz[y]>siz[Son[x]]){Son[x]=y;}}}}void dfs2(int x,int z){int i,y;dfn[x]=++tim;tp[x]=z;if(Son[x]){dfs2(Son[x],z);for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if(!dfn[y]){dfs2(y,y);}}}}int lca(int x,int y){while(tp[x]!=tp[y]){if(dep[tp[x]]<dep[tp[y]]){swap(x,y);}x=fa[tp[x]];}return dep[x]<dep[y]?x:y;}void change(int &x,int xx,int y,int z,int l,int r,ll ts,ll tc){x=++tot;memcpy(son[x],son[xx],sizeof(son[x]));sum[x]=sum[xx];st[x]=st[xx];c[x]=c[xx];if(y==l&&z==r){st[x]+=ts;c[x]+=tc;return ;}sum[x]+=(ts+ts+tc*(r-l))*(r-l+1)/2;int mid=y+z>>1;if(r<=mid){change(son[x][0],son[xx][0],y,mid,l,r,ts,tc);}else if(l>mid){change(son[x][1],son[xx][1],mid+1,z,l,r,ts,tc);}else{change(son[x][0],son[xx][0],y,mid,l,mid,ts,tc);change(son[x][1],son[xx][1],mid+1,z,mid+1,r,ts+(mid-l+1)*tc,tc);}}ll ask(int x,int y,int z,int l,int r){ll re=(st[x]+(l-y)*c[x]+st[x]+(r-y)*c[x])*(r-l+1)/2;if(y==l&&z==r){return re+sum[x];}int mid=y+z>>1;if(r<=mid){return re+ask(son[x][0],y,mid,l,r);}else if(l>mid){return re+ask(son[x][1],mid+1,z,l,r);}else{return re+ask(son[x][0],y,mid,l,mid)+ask(son[x][1],mid+1,z,mid+1,r);}}void tochange(ll ts,ll tc,int x,int y){int l=lca(x,y);ll xx=0,xy=dep[x]+dep[y]-dep[l]*2+1+1;while(tp[x]!=tp[l]){xx+=dep[x]-dep[tp[x]]+1;change(rt[now],rt[now],1,n,dfn[tp[x]],dfn[x],ts+(xx-1)*tc,-tc);x=fa[tp[x]];}while(tp[y]!=tp[l]){xy-=dep[y]-dep[tp[y]]+1;change(rt[now],rt[now],1,n,dfn[tp[y]],dfn[y],ts+(xy-1)*tc,tc);y=fa[tp[y]];}xx++;xy--;if(dep[x]<dep[y]){change(rt[now],rt[now],1,n,dfn[x],dfn[y],ts+(xx-1)*tc,tc);}else{change(rt[now],rt[now],1,n,dfn[y],dfn[x],ts+(xy-1)*tc,-tc);}}ll toask(int x,int y){ll re=0;while(tp[x]!=tp[y]){if(dep[tp[x]]<dep[tp[y]]){swap(x,y);}re+=ask(rt[now],1,n,dfn[tp[x]],dfn[x]);x=fa[tp[x]];}if(dep[x]>dep[y]){swap(x,y);}re+=ask(rt[now],1,n,dfn[x],dfn[y]);return re;}int main(){int i;ll x,y;ll ts,tc;scanf("%d%d",&n,&m);char o[2];for(i=1;i<n;i++){scanf("%d%d",&x,&y);bde(x,y);}dfs1(1);dfs2(1,1);while(m--){scanf("%s",o);if(o[0]=='c'){scanf("%lld%lld%lld%lld",&x,&y,&ts,&tc);x^=la;y^=la;rt[++TOT]=rt[now];now=TOT;tochange(ts,tc,x,y);}if(o[0]=='q'){scanf("%lld%lld",&x,&y);x^=la;y^=la;printf("%lld\n",la=toask(x,y));}if(o[0]=='l'){scanf("%lld",&x);x^=la;now=x;}}return 0;}/*5 71 22 33 44 5c 2 5 2 3c 3 4 5 10q 1 3l 13q 13 15l 6q 6 4*/


0 0