給一棵n個帶點權節點(初始為0)的樹
有三種操作:
1,對一條路徑上的點的點權全部增加乙個數
2,求一條路徑上的點的點權和
3,對一條路徑進行輪換(假如路徑為a_1~a_k則a_1–>a_2,a_2–>a_3….a_k–>a_1)
容易想到用lct維護,輪換操作可以直接把左端點接到右端點的右兒子處,但這樣會改變樹的形態,具體實現就是把權值和形態分開來維護,維護樹的形態的lct中,每個splay的root記錄對應的權值splay的某乙個點(不一定是該splay的root,我們可以訪問的時候在跳到root,同時更新一下即可)
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define ll long long
#define l tree[x][0]
#define r tree[x][1]
using
namespace
std;
int w;char ch;
inline
int read()
const
int maxn=1e5+5;
int i,j,n,q[maxn],cnt,k[maxn],next[maxn*2],g[maxn*2],num,qs;
struct tsplay
void update(int x)
void ins(int x,int v)
void add(int x,int v)
void re(int x)
void clear(int x)
void chu(int x)
void rotate(int x)
void splay(int x)rotate(x);
}update(x);
}int root(int &x)
int kth(int &x,int k)
}void turn(int x)
}val;
struct tlct
void update(int x)
void ins(int x,int f,int v)
void re(int x)
void clear(int x)
void chu(int x)
void rotate(int x)
void splay(int x)rotate(x);
}update(x);
}void access(int x)
if (last)
val.update(x2),update(x);}}
void makeroot(int x)
void path(int x,int y)
}lct;
void add(int x,int y)
char c[10];
void pint(ll x)
void dfs(int x,int y)
}int main()else
if (c[1]=='q') pint(val.sum[ro]),putchar('\n');
else
if (x!=y)val.turn(ro);
}}
GDSOI2017 中學生資料結構題
第一行有乙個整數 n,表示 s 國城市的數量。接下來有 n 1 行,每行兩個數 u,v 表示一條道路。第 n 1 行為乙個整數 q,表示接下來有 q 個操作。接下來有 q 行,每行表示乙個操作,格式如題目描述所示。對於每乙個 query 操作,輸出乙個數,表示詢問的當前編號為 x 和編號為 y 的城...
GDSOI2017 中學生資料結構題(LCT)
雖然這只是sone0裡很小的一部分,但是我認為這是最煩的一部分,對著乙個錯誤的題目調了兩天tat 最後才發現自己的程式的輪換打反了 如果想直接用一棵lct來做有乙個最簡單的想法,就是把x到y這段提取出來,然後再輪換一下。但是,這個想法明顯有問題,因為輪換的時候只是換了一下相對順序,並沒有交換權值的大...
GDSOI2017 中學生資料結構題 Lct練習
給出一棵樹。要求維護 一條路徑上的點權和。修改1 一條路徑上的點的點權全部加上乙個數。修改2 shift 假設乙個路徑上的點是ax,ak1,ak2,ay 就把ax的點權放到ak1上,把ak1的點權放到ak2上,把ay的點權放到ax上。我連去soi的資格都沒有 當時去聽講,不會splay,不會lct,...