BZOJ2759 一个动态树好题
題目
有\(N\)個未知數(shù)\(x[1..n]\)和\(N\)個等式組成的同余方程組:
\(x[i]=k[i]*x[p[i]]+b[i] mod 10007\)
 其中,\(k[i],b[i],x[i]∈[0,10007)∩Z\)
 你要應(yīng)付\(Q\)個事務(wù),每個是兩種情況之一:
 一.詢問當(dāng)前\(x[a]\)的解
\(A\ a\)
 無解輸出-1
\(x[a]\)有多解輸出-2
 否則輸出\(x[a]\)
 二.修改一個等式
\(C\ a\ k[a]\ p[a]\ b[a]\)
思路1
此題一直有點迷,在paulliant大佬的指點下,勉強口胡一份題解。
首先不難發(fā)現(xiàn),這是一個樹形結(jié)構(gòu),每個點僅有一條有向出邊,知道了每個點的父親就能知道這個點,所以這是一棵基環(huán)樹,然后我們用一個結(jié)構(gòu)體表示當(dāng)前點與它父親的依賴關(guān)系。\((K,B)\)表示\(x=fa[x]*K+B\)
由于是單向邊的有根樹,所以每條邊都指向它的父親。所以對于LCT中的一條路徑\((u,v)\)來說,\(sum[rt]=(node){K,B}\)表示\(u=Kv+B\),合并什么的還是很好推的。
還有一題小R與手機和此題有幾分相像。
struct node{int k,b;node operator + (const node& res)const{return (node){k*res.k%P,(res.k*b%P+res.b)%P};} }然后如果存在了環(huán)的話,可以先把它存下來,等之后有點被刪掉了之后在加上去。之后詢問的時候由于形成了環(huán),所以就可以得到解的情況了。
代碼
#include<bits/stdc++.h> #define M 100005 using namespace std; const int P=1e4+7; int inv[M],Ifa[M]; int n; struct node{int k,b;node operator + (const node& res)const{return (node){k*res.k%P,(res.k*b%P+res.b)%P};} }val[M],sum[M]; struct LCT{int ch[M][2],fa[M];void up(int p){sum[p]=sum[ch[p][0]]+val[p]+sum[ch[p][1]];}void create(int x,node d){ch[x][0]=ch[x][1]=fa[x]=0;val[x]=sum[x]=d;}bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}void rotate(int x){int y=fa[x],z=fa[y],k=ch[y][1]==x;if(!isrt(y))ch[z][ch[z][1]==y]=x;fa[x]=z;ch[y][k]=ch[x][!k];fa[ch[x][!k]]=y;ch[x][!k]=y;fa[y]=x;up(y);up(x);}void splay(int x){while(!isrt(x)){int y=fa[x],z=fa[y];if(!isrt(y))(ch[y][1]==x^ch[z][1]==y)?rotate(x):rotate(y);rotate(x);}}void access(int x){for(int y=0;x;y=x,x=fa[x])splay(x),ch[x][1]=y,up(x);}int findrt(int x){access(x);splay(x);while(ch[x][0])x=ch[x][0];splay(x);return x;}bool link(int x,int y){splay(x);if(findrt(y)==x)return 0;fa[x]=y;return 1;}bool cut(int x){access(x),splay(x);if(!ch[x][0])return 0;fa[ch[x][0]]=0;ch[x][0]=0;up(x);return 1;}void update(int x,node d){val[x]=sum[x]=d;up(x);splay(x);}node query(int x){access(x),splay(x);return sum[x];}void Link(int x,int y){if(!link(x,y))Ifa[x]=y;}void Cut(int x){int y=findrt(x);if(!cut(x)){Ifa[x]=0;return;}if(link(y,Ifa[y]))Ifa[y]=0;}int solve(int x){int y=findrt(x),z=Ifa[y];node f=query(z);if(f.k==1)return f.b==0?-2:-1;int vl=f.b*inv[(P+1-f.k)%P]%P;f=query(x);return (f.k*vl+f.b)%P;} }Tr; int main(){inv[0]=inv[1]=1;for(int i=2;i<=P-1;i++)inv[i]=(P-P/i)*inv[P%i]%P;scanf("%d",&n);for(int i=0;i<=n;i++)Tr.create(i,(node){1,0});for(int i=1;i<=n;i++){int k,p,b;scanf("%d%d%d",&k,&p,&b);Tr.update(i,(node){k,b});Tr.Link(i,p);}int q;scanf("%d",&q);while(q--){char op[5];int a,k,p,b;scanf("%s",op);if(op[0]=='A'){scanf("%d",&a);printf("%d\n",Tr.solve(a));}else {scanf("%d%d%d%d",&a,&k,&p,&b);Tr.update(a,(node){k,b});Tr.Cut(a);Tr.Link(a,p);}}return 0; }[BZOJ 2759 一個動態(tài)樹好題(動態(tài)樹)]?
轉(zhuǎn)載于:https://www.cnblogs.com/zryabc/p/10701390.html
總結(jié)
以上是生活随笔為你收集整理的BZOJ2759 一个动态树好题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: http dns djang
- 下一篇: 图像处理笔记(八)
