闲来无事水一发毒瘤题
链剖+主席树即可
区间加一个等差数列标记合并的时候把首项和公差都加起来就好了
因为区间修改所以要标记永久化,除了标记以外还要记录子树内因更改所增加的和
#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-8
struct 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 7
1 2
2 3
3 4
4 5
c 2 5 2 3
c 3 4 5 10
q 1 3
l 13
q 13 15
l 6
q 6 4
*/