日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ 2759 一个动态树好题 (LCT)

發布時間:2025/3/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ 2759 一个动态树好题 (LCT) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

滾回來學文化課了……

題目鏈接

https://www.lydsy.com/JudgeOnline/problem.php?id=2759

題解

LCT,顯然的做法是維護鏈上所有一次函數的復合。
如何處理根的問題?

考慮所有的連通塊都建成有根樹,另外記錄每個根的父親。
修改父親的時候,如果修改的是根,那么要么直接改,要么合并兩個連通塊,根變為非根;如果修改的不是根,要特判分裂了兩個連通塊導致根的父親進了新的連通塊的情況,如果如此則需重新合并,根變為非根,其余直接改即可。

時間復雜度\(O(n\log n)\).

代碼

#include<cstdio> #include<cstdlib> #include<iostream> #include<cassert> using namespace std;void read(int &x) {int f=1;x=0;char s=getchar();while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}x*=f; }const int N = 3e4; const int P = 1e4+7; int inv[P+2]; struct Data {int a,b;Data() {}Data(int _a,int _b) {a = _a,b = _b;}Data operator *(const Data &arg) const {return Data(a*arg.a%P,(b*arg.a+arg.b)%P);}int calc(int x) {return (a*x+b)%P;}int solve(){if(a==0) {return b==0?-2:-1;}return inv[a]*(P-b)%P;} }; int fa[N+3]; int uf[N+3]; int n,q;int findfa(int u) {int i = u;while(u!=uf[u]) {u = uf[u];}while(u!=uf[i]){int j = uf[i]; uf[i] = u; i = j;}return u; }struct SplayNode {int son[2],fa; Data val,sum; } spl[N+3]; bool isroot(int u) {return spl[spl[u].fa].son[0]!=u && spl[spl[u].fa].son[1]!=u;} void pushup(int u) {int ls = spl[u].son[0],rs = spl[u].son[1];spl[u].sum = spl[u].val;if(ls) {spl[u].sum = spl[ls].sum*spl[u].sum;}if(rs) {spl[u].sum = spl[u].sum*spl[rs].sum;} } void rotate(int u) {int x = spl[u].fa,y = spl[x].fa,dir = u==spl[x].son[0];if(!isroot(x)) {spl[y].son[x==spl[y].son[1]] = u;}spl[u].fa = y;spl[x].son[dir^1] = spl[u].son[dir];if(spl[u].son[dir]) {spl[spl[u].son[dir]].fa = x;}spl[u].son[dir] = x; spl[x].fa = u;pushup(x); } void splaynode(int u) {int x = u;while(!isroot(x)){x = spl[x].fa;}while(!isroot(u)){int y = spl[u].fa,z = spl[y].fa;if(!isroot(y)) {(u==spl[y].son[1])^(y==spl[z].son[1]) ? rotate(u) : rotate(y);}rotate(u);}pushup(u); } void access(int u) {for(int i=0; u; i=u,u=spl[u].fa){splaynode(u);spl[u].son[1] = i;pushup(u);} } int findroot(int u,int flg=0) {access(u); splaynode(u);while(spl[u].son[0]) u = spl[u].son[0];if(flg) splaynode(u);return u; } void link(int u,int v) //fa[u]=v { // printf("link %d %d\n",u,v);access(u); splaynode(u);spl[u].fa = v; } void cut(int u) //fa[u]=v { // printf("cut %d\n",u);access(u); splaynode(u);int v = spl[u].son[0]; spl[u].son[0] = spl[v].fa = 0;pushup(u); } void modify(int u,Data x) {splaynode(u);spl[u].val = x; }int main() {inv[1] = 1; for(int i=2; i<P; i++) inv[i] = P-(P/i*inv[P%i]%P);scanf("%d",&n);for(int i=1; i<=n; i++) uf[i] = i;for(int i=1; i<=n; i++){int u,x,y; scanf("%d%d%d",&x,&u,&y);spl[i].val = spl[i].sum = Data(x,y);int uu = findfa(u);if(uu==i){fa[i] = u;}else{link(i,u);uf[findfa(i)] = uu;}}scanf("%d",&q);while(q--){char opt[5]; scanf("%s",opt+1);if(opt[1]=='A'){int u; scanf("%d",&u);int rt = findroot(u);access(fa[rt]); splaynode(fa[rt]);int x = Data((spl[fa[rt]].sum.a-1+P)%P,spl[fa[rt]].sum.b).solve();if(x<0) {printf("%d\n",x);}else{access(u); splaynode(u);int ans = spl[u].sum.calc(x);printf("%d\n",ans);}}else if(opt[1]=='C'){int u,ax,ay,v; scanf("%d%d%d%d",&u,&ax,&v,&ay);modify(u,Data(ax,ay));if(fa[u]){int rtv = findroot(v);if(rtv==u) {fa[u] = v;}else{fa[u] = 0;link(u,v);}}else{int rt = findroot(u);cut(u);int rtf = findroot(fa[rt]);if(rtf==u){link(rt,fa[rt]);fa[rt] = 0;}int rtv = findroot(v);if(rtv==u) {fa[u] = v;}else {link(u,v);}}}}return 0; } 與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的BZOJ 2759 一个动态树好题 (LCT)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。