GDSOI2017 中學生資料結構題(LCT)

2021-08-01 09:02:33 字數 2367 閱讀 7582

雖然這只是sone0裡很小的一部分,但是我認為這是最煩的一部分,對著乙個錯誤的題目調了兩天tat(最後才發現自己的程式的輪換打反了)。

如果想直接用一棵lct來做有乙個最簡單的想法,就是把x到y這段提取出來,然後再輪換一下。但是,這個想法明顯有問題,因為輪換的時候只是換了一下相對順序,並沒有交換權值的大小,就是說在下一次詢問編號的時候,原來的點x權值c,換了之後,還是會訪問到點x和權值c。這樣權值就根本沒有換過。

我們現在就發現了,編號是乙個很麻煩的東西。

所以,我們可以考慮一下,權值只維護相對位置,然後再次同時我們再維護一下它的編號,這樣權值就可以和編號一一對應了。但是我們還是會發現這樣是不能詢問編號的,所以我們只能把編號打出來,再建一棵編號lct,因為是從前面的權值lct打出來的,那麼這個權值lct的中序遍歷(相對順序)和編號lct的中序遍歷(相對順序)是一一對應的。因為要一一對應,所以我們在access的時候,兩棵lct要一起變動,換根的時候深度標記也要一起翻轉。

因為編號lct上的編號是不會變化的,編號和原樹是一樣的。

那麼在詢問編號x到編號y上的資訊的時候,(因為兩個lct的相對順序是一樣的,所以access和makeroot的時候都是打在一起的,因為還要兩個一起修改樹的結構),先在樹上把編號x到y放到一起,然後再尋找此時在權值lct上對應的點,然後當前這個點的splay與x(或y)所在的splay是一一對應的,那麼直接修改或查詢即可。

輪換的時候,知道權值的那一段,然後直接修改權值的相對順序就可以了。

看到這裡,肯定有乙個很明顯的問題,怎樣在編號lct的x節點找到對應的權值lct的節點。

我們記錄乙個g[0][x]和g[1][x]分別表示(0是權值的,1是編號的),權值lctx對應編號lct的根節點,編號lctx對應權值lct的根節點。我們知道lct上有很多個虛邊,那麼頭上是虛邊的那個就是虛邊下面splay的根節點,所以我們記錄這些根節點一一對應,不是根節點的點沒有g值。所以g要在access和輪換和rotate的時候更新。

找到對應的根節點之後就很好辦了,因為找出來的那個splay是和當前被找的那個splay相對順序一樣的,所以在另外那麼的splay找x的時候,只用找中序遍歷為size[t[0][x]]+1(及x在0【或1】樹上的中序遍歷)的節點即可。

維護虛邊的時候其實只用打乙個陣列,因為只有編號對應的lct才是和原樹的編號對應的。

#include

#include

#include

#include

#include

#define fo(i,a,b) for(i=a;i<=b;i++)

#define rep(i,a) for(i=first[a];i;i=next[i])

using namespace std;

typedef long long ll;

const int maxn=2e5+7;

int i,j,k,l,n,m,ans,p,q,u;

int t[2][maxn][2],pfa[maxn],f[2][maxn],bz[2][maxn],d[maxn];

int first[maxn],last[maxn],next[maxn],num,x,y,g[2][maxn];

ll sum[2][maxn],ad[2][maxn],a[2][maxn],size[2][maxn],z;

char s[9];

void add(int x,int y)

int son(int o,int x)

void update(int o,int x)

void gao(int o,int x,ll y)

void down(int o,int x)

if(ad[o][x])

}void remove(int o,int x,int y)

void rotate(int o,int x)

void splay(int o,int x,int y)

}int kth(int o,int x,int k)

int find(int x)

void access(int x)

}void makeroot(int x)

void dfs(int x,int y)

int main()

dfs(1,0);

for(scanf("%d",&m);m;m--)

else if(s[0]=='q')printf("%lld\n",sum[0][y]);

else

}}

GDSOI2017 中學生資料結構題

第一行有乙個整數 n,表示 s 國城市的數量。接下來有 n 1 行,每行兩個數 u,v 表示一條道路。第 n 1 行為乙個整數 q,表示接下來有 q 個操作。接下來有 q 行,每行表示乙個操作,格式如題目描述所示。對於每乙個 query 操作,輸出乙個數,表示詢問的當前編號為 x 和編號為 y 的城...

GDSOI2017 中學生資料結構題 Lct練習

給出一棵樹。要求維護 一條路徑上的點權和。修改1 一條路徑上的點的點權全部加上乙個數。修改2 shift 假設乙個路徑上的點是ax,ak1,ak2,ay 就把ax的點權放到ak1上,把ak1的點權放到ak2上,把ay的點權放到ax上。我連去soi的資格都沒有 當時去聽講,不會splay,不會lct,...

中學生資料結構題

給一棵n個帶點權節點 初始為0 的樹 有三種操作 1,對一條路徑上的點的點權全部增加乙個數 2,求一條路徑上的點的點權和 3,對一條路徑進行輪換 假如路徑為a 1 a k則a 1 a 2,a 2 a 3 a k a 1 容易想到用lct維護,輪換操作可以直接把左端點接到右端點的右兒子處,但這樣會改變...