标签:spl 比较 不能 next swap \n splay struct wan
树链剖分若不会的话可自行学习一下.
前两种操作是线性变换,模\(2^{64}\)可将线段树全部用unsigned long long 保存,另其自然溢出.
而取反操作比较不能直接处理,因为其模\(2^{64}\)的特殊性,可将其转化为线性变换.
显然
\[-x\equiv (2^{64}-1)*x (mod\ 2^{64})\]
因为\[!x = (2^{64}-1) -x \]
所以
\[ !x = (2^{64}-1) + (2^{64}-1)x\]
#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define Lson l,m,lson
#define Rson m+1,r,rson
typedef unsigned long long LL;
LL TTT = 0xffffffffffffffff;
using namespace std;
const int maxn =1e5+5;
struct Edge{
int to,next;
}E[2*maxn];
int n,head[maxn],tot;
int cnt,idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],id[maxn],rnk[maxn];
void init()
{
cnt=idx=tot=0;
memset(head,-1,sizeof(head));
dep[1]=0,fa[1]=1,size[0]=0;
memset(son,0,sizeof(son));
}
void AddEdge(int u,int v)
{
E[tot] = (Edge){v,head[u]};
head[u]=tot++;
}
void dfs1(int u)
{
size[u]=1;
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
}
void dfs2(int u,int topu)
{
top[u]= topu;
id[u] = ++idx;
rnk[idx] = u;
if(!son[u]) return;
dfs2(son[u],top[u]);
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
struct Node{
LL sum,add,b;
bool nt;
}tree[maxn<<2];
void pushup(int rt){
tree[rt].sum = tree[lson].sum + tree[rson].sum;
}
void pushdown(int l,int r,int rt)
{
int m = (l+r)>>1;
if(tree[rt].add!=1){
tree[lson].sum *= tree[rt].add;
tree[rson].sum *= tree[rt].add;
tree[lson].b *= tree[rt].add;
tree[rson].b *= tree[rt].add;
tree[lson].add *= tree[rt].add;
tree[rson].add *= tree[rt].add;
tree[rt].add = 1;
}
if(tree[rt].b){
tree[lson].sum += (m-l+1)* tree[rt].b;
tree[rson].sum += (r-m) *tree[rt].b;
tree[lson].b += tree[rt].b;
tree[rson].b += tree[rt].b;
tree[rt].b= 0;
}
}
void build(int l,int r,int rt)
{
tree[rt].add =1;
tree[rt].b =0;
tree[rt].nt = 0;
if(l==r){
tree[rt].sum = 0;
return;
}
int m = (l+r)>>1;
build(Lson);
build(Rson);
pushup(rt);
}
void update(int L,int R,LL k,LL b,int l=1,int r=n,int rt=1)
{
if(L<=l && R>=r){
tree[rt].sum *= k;
tree[rt].add *= k;
tree[rt].b *= k;
tree[rt].sum += (r-l+1)*b;
tree[rt].b +=b;
tree[rt].nt = 0;
return;
}
pushdown(l,r,rt);
int m = (l+r)>>1;
if(L<=m) update(L,R,k,b,Lson);
if(R>m) update(L,R,k,b,Rson);
pushup(rt);
}
LL query(int L,int R,int l=1,int r= n,int rt=1)
{
if(L<=l && R>=r){
return tree[rt].sum;
}
pushdown(l,r,rt);
LL ans=0;
int m = (l+r)>>1;
if(L<=m) ans += query(L,R,Lson);
if(R>m) ans += query(L,R,Rson);
return ans;
}
void change(int u,int v,int op,LL val)
{
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
if(op==1){
update(id[top[u]],id[u],(LL)1,val);
}
else if(op==2){
update(id[top[u]],id[u],val,0);
}
else{
update(id[top[u]],id[u],TTT,TTT);
}
u = fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
if(op==1){
update(id[u],id[v],(LL)1,val);
}
else if(op==2){
update(id[u],id[v],val,0);
}
else{
update(id[u],id[v],TTT,TTT);
}
return ;
}
LL Qsum(int u,int v)
{
LL ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
ans += query(id[top[u]],id[u]);
u = fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
ans += query(id[u],id[v]);
return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int u,v,Q;
while(scanf("%d",&n)==1){
init();
for(int i=2;i<=n;++i){
scanf("%d",&u);
AddEdge(u,i);
AddEdge(i,u);
}
dfs1(1);
dfs2(1,1);
build(1,n,1);
scanf("%d",&Q);
int op;
LL tmp;
while(Q--){
scanf("%d",&op);
if(op==1){
scanf("%d %d %lld",&u, &v, &tmp);
change(u,v,2,tmp);
}
else if(op==2){
scanf("%d %d %llu",&u, &v,&tmp);
change(u,v,1,tmp);
}
else if(op==3){
scanf("%d %d",&u, &v);
change(u,v,3,0);
}
else{
scanf("%d %d",&u, &v);
printf("%llu\n",Qsum(u,v));
}
}
}
return 0;
}
ACM-ICPC 2018 焦作赛区网络预赛 E. Jiu Yuan Wants to Eat (树链剖分-线性变换线段树)
标签:spl 比较 不能 next swap \n splay struct wan
原文地址:https://www.cnblogs.com/xiuwenli/p/9651737.html