# [2018HN省队集训D1T1] Tree

## 题意

• 1 rootroot 设为根.
• 2 u v d 将以 $$\operatorname{LCA} (u,v)$$ 为根的子树中的点权值加上 $$d$$.
• 3 u 查询以 $$u$$ 为根的子树中的点的权值之和.

$$n,q\le3\times 10^5$$

## 题解

### 参考代码

#include <bits/stdc++.h>

const int MAXE=1e6+10;
const int MAXV=3e5+10;
typedef long long intEx;

struct Edge{
int from;
int to;
Edge* next;
};
Edge E[MAXE];
Edge* top=E;

struct LCT{
#define lch chd[0]
#define rch chd[1]
#define kch chd[k]
#define xch chd[k^1]
struct Node{
int id;
bool rev;
Node* prt;
Node* pprt;
Node* chd[2];
Node(int id):id(id),rev(false),prt(NULL),pprt(NULL),chd{NULL,NULL}{}
inline void Flip(){
if(this!=NULL){
this->rev=!this->rev;
std::swap(this->lch,this->rch);
}
}
inline void PushDown(){
if(this!=NULL&&this->rev){
this->lch->Flip();
this->rch->Flip();
this->rev=false;
}
}
};
std::vector<Node*> N;
LCT(int n):N(n+1){
for(int i=1;i<=n;i++)
N[i]=new Node(i);
}
inline void Rotate(Node* root,int k){
Node* tmp=root->xch;
root->PushDown();
tmp->PushDown();
tmp->prt=root->prt;
if(root->prt==NULL){
tmp->pprt=root->pprt;
root->pprt=NULL;
}
else if(root->prt->lch==root)
root->prt->lch=tmp;
else
root->prt->rch=tmp;
root->xch=tmp->kch;
if(root->xch!=NULL)
root->xch->prt=root;
tmp->kch=root;
root->prt=tmp;
}
inline void Splay(Node* root){
while(root->prt!=NULL){
int k=root->prt->lch==root;
if(root->prt->prt==NULL)
Rotate(root->prt,k);
else{
int d=root->prt->prt->lch==root->prt;
Rotate(k==d?root->prt->prt:root->prt,k);
Rotate(root->prt,d);
}
}
}
inline void Expose(Node* root){
Splay(root);
root->PushDown();
if(root->rch!=NULL){
root->rch->prt=NULL;
root->rch->pprt=root;
root->rch=NULL;
}
}
inline	Node* Access(Node* root){
Expose(root);
Node* ret=root;
while(root->pprt!=NULL){
ret=root->pprt;
Expose(root->pprt);
root->pprt->rch=root;
root->prt=root->pprt;
root->pprt=NULL;
Splay(root);
}
return ret;
}
inline	void Evert(Node* root){
Access(root);
Splay(root);
root->Flip();
}
inline	void Evert(int root){
Evert(N[root]);
}
Evert(N[son]);
N[son]->pprt=N[prt];
}
inline	int LCA(int x,int y){
Access(N[x]);
return Access(N[y])->id;
}
#undef lch
#undef rch
#undef kch
#undef xch
};

struct Node{
int l;
int r;
intEx sum;
Node* lch;
Node* rch;
Node(int,int);
void Maintain();
void PushDown();
intEx Query(int,int);
};

int n;
int q;
int clk;
int val[MAXV];
int pos[MAXV];
int dfn[MAXV];
int deep[MAXV];
int size[MAXV];
int prt[20][MAXV];

void Insert(int,int);
int Ancestor(int,int);
void DFS(int,int,int);

int main(){
for(int i=1;i<=n;i++)
LCT* T=new LCT(n);
for(int i=1;i<n;i++){
int a,b;
Insert(a,b);
Insert(b,a);
}
DFS(1,0,0);
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j<=n;j++)
prt[i][j]=prt[i-1][prt[i-1][j]];
Node* N=new Node(1,n);
T->Evert(1);
int root=1;
for(int i=0;i<q;i++){
int t;
if(t==1){
T->Evert(root);
}
else if(t==2){
int a,b,d;
int lca=T->LCA(a,b);
if(lca==root)
else if(deep[lca]>=deep[root])
else if(Ancestor(root,deep[root]-deep[lca])==lca){
int x=Ancestor(root,deep[root]-deep[lca]-1);
}
else
}
else if(t==3){
int r;
intEx ans=0;
if(r==root)
ans=N->Query(1,n);
else if(deep[r]>=deep[root])
ans=N->Query(dfn[r],dfn[r]+size[r]-1);
else if(Ancestor(root,deep[root]-deep[r])==r){
int x=Ancestor(root,deep[root]-deep[r]-1);
ans+=N->Query(1,n);
ans-=N->Query(dfn[x],dfn[x]+size[x]-1);
}
else
ans=N->Query(dfn[r],dfn[r]+size[r]-1);
printf("%lld\n",ans);
}
}
return 0;
}

inline int Ancestor(int cur,int k){
for(int i=0;(1<<i)<=k;i++)
if((1<<i)&k)
cur=prt[i][cur];
return cur;
}

void DFS(int root,int prt,int deep){
::size[root]=1;
::dfn[root]=++clk;
::deep[root]=deep;
::prt[0][root]=prt;
::pos[dfn[root]]=root;
if(i->to!=prt){
DFS(i->to,root,deep+1);
size[root]+=size[i->to];
}
}
}

inline void Insert(int from,int to){
top->from=from;
top->to=to;
}

if(l==r)
sum=val[pos[l]];
else{
int mid=(l+r)>>1;
this->lch=new Node(l,mid);
this->rch=new Node(mid+1,r);
this->sum=this->lch->sum+this->rch->sum;
}
}

void Node::Add(int l,int r,const intEx& d){
if(l<=this->l&&this->r<=r)
else{
this->PushDown();
if(l<=this->lch->r)
if(this->rch->l<=r)
this->Maintain();
}
}

intEx Node::Query(int l,int r){
if(l<=this->l&&this->r<=r)
return this->sum;
else{
this->PushDown();
if(r<=this->lch->r)
return this->lch->Query(l,r);
if(this->rch->l<=l)
return this->rch->Query(l,r);
return this->lch->Query(l,r)+this->rch->Query(l,r);
}
}

void Node::Maintain(){
this->sum=this->lch->sum+this->rch->sum;
}

void Node::PushDown(){
}
}

this->sum+=d*(r-l+1);
}

target=0;
int sgn=1;
register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')
sgn=-sgn;
ch=getchar();
}
while(isdigit(ch)){
target=target*10+ch-'0';
ch=getchar();
}
target*=sgn;
}



posted @ 2019-02-28 15:50  rvalue  阅读(316)  评论(0编辑  收藏  举报