1. 程式人生 > >bzoj4530:[Bjoi2014]大融合

bzoj4530:[Bjoi2014]大融合

splay AR pre namespace LG flip define aps HA

傳送門

題意:

一開始有n棵單點的樹,每次連接兩個點(保證仍未樹結構),或者詢問某課樹中經過某條邊的簡單路徑條數。

lct維護子樹信息。

一個點維護兩個值sum表示子樹信息,sz表示它所有虛兒子的信息,sum[x]=sum[lc]+sum[rc]+sz[x]+1;

發現僅有access和link時sz會改變。(cut時切掉的是實兒子)

access是把右兒子換成t,sz[x]就減去sum[t],加上sum[rc];

link時給x接上新的虛兒子y,就sz[x]+=sum[y],但是要先把access再splay到跟,因為不然x的父親往上的信息也需要要改。

其實還沒交,不知道代碼過沒,先碼這。

技術分享圖片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const
int N=3e5+7; typedef long long LL; typedef double db; using namespace std; int n,m,v[N],ch[N][2],p[N],sum[N],flip[N],sz[N]; char o[5]; template<typename T> void read(T &x) { T f=1; x=0; char ch=getchar(); while(ch!=-&&(ch<0||ch>9)) ch=getchar(); if(ch==-) f=-1
,ch=getchar(); for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f; } #define lc ch[x][0] #define rc ch[x][1] int isroot(int x) { return (ch[p[x]][0]!=x&&ch[p[x]][1]!=x); } void update(int x) { sum[x]=sum[lc]+sum[rc]+sz[x]+1; } //sum:總信息 sz:虛兒子信息 void down(int x) { if(!flip[x]) return; swap(lc,rc); flip[x]^=1; flip[lc]^=1; flip[rc]^=1; } void rotate(int x) { int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1; if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z; ch[y][l]=ch[x][r]; p[ch[x][r]]=y; ch[x][r]=y; p[y]=x; update(y); update(x); } void splay(int x) { static int g[N],top=0,tp; for(tp=x;!isroot(tp);tp=p[tp]) g[++top]=tp; g[++top]=tp; while(top) {down(g[top--]);} for(;!isroot(x);rotate(x)) { int y=p[x],z=p[y]; if(!isroot(y)) ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y); } } void access(int x) { for(int t=0;x;x=p[t=x]) { splay(x); sz[x]+=sum[rc]-sum[t]; rc=t; update(x); } } void newroot(int x) { access(x); splay(x); flip[x]^=1; } void lik(int x,int y) { newroot(x); newroot(y); splay(x); p[x]=y; sz[y]+=sum[x]; update(y); } int main() { read(n); read(m); for(int i=1;i<=n;i++) update(i); while(m--) { scanf("%s",o); int x,y; read(x); read(y); if(o[0]==A) lik(x,y); else { newroot(x); newroot(y); printf("%lld\n",(LL)sum[x]*(sum[y]-sum[x])); } } return 0; }
View Code

bzoj4530:[Bjoi2014]大融合