BZOJ2759 一个动态树好题 LCT
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ2759
题意概括
Description
有N个未知数x[1..n]和N个等式组成的同余方程组:
x[i]=k[i]*x[p[i]]+b[i] mod 10007
其中,k[i],b[i],x[i]∈[0,10007)∩Z
你要应付Q个事务,每个是两种情况之一:
一.询问当前x[a]的解
A a
无解输出-1
x[a]有多解输出-2
否则输出x[a]
二.修改一个等式
C a k[a] p[a] b[a]
Input
N
下面N行,每行三个整数k[i] p[i] b[i]
Q
下面Q行,每行一个事务,格式见题目描述
Output
对每个询问,输出一行一个整数。
对100%的数据,1≤N≤30000,0≤Q≤100000,时限2秒,其中询问事务约占总数的80%
题解
这题不大会,基本上是抄的……
rev标记不用打,大概是因为不用link和cut吧。
大佬题解:
http://blog.csdn.net/qq_30401759/article/details/50649672
代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=30005,Mod=10007;
struct fc{
int k,b;
fc (){k=1,b=0;}
fc (int k_,int b_){k=k_,b=b_;}
int calc(int x){
return (k*x+b)%Mod;
}
};
fc operator + (fc a,fc b){
return fc(a.k*b.k%Mod,(b.k*a.b+b.b)%Mod);
}
int Pow(int x,int y){
if (y==0)
return 1;
int xx=Pow(x,y/2);
xx=xx*xx%Mod;
if (y&1)
xx=xx*x%Mod;
return xx;
}
int Inv(int a){
return Pow(a%Mod,Mod-2);
}
int fa[N],son[N][2],sfa[N];
fc val[N],sum[N];
bool isroot(int x){
return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
void pushup(int x){
sum[x]=sum[son[x][0]]+val[x]+sum[son[x][1]];
}
int wson(int x){
return son[fa[x]][1]==x;
}
void rotate(int x){
if (isroot(x))
return;
int y=fa[x],z=fa[y],L=wson(x),R=L^1;
if (!isroot(y))
son[z][wson(y)]=x;
fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
son[y][L]=son[x][R],son[x][R]=y;
pushup(y),pushup(x);
}
void splay(int x){
for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
if (!isroot(y))
rotate(wson(x)==wson(y)?y:x);
}
void access(int x){
for (int t=0;x;t=x,x=fa[x]){
splay(x);
son[x][1]=t;
pushup(x);
}
}
void link(int x,int y){
access(x);
splay(x);
fa[x]=y;
}
void cut(int x){
access(x);
splay(x);
fa[son[x][0]]=0;
son[x][0]=0;
pushup(x);
}
int find(int x){
access(x);
splay(x);
while (son[x][0])
x=son[x][0];
splay(x);
return x;
}
int query(int x){
access(x);
splay(x);
fc a=sum[x];
int rt=find(x),spfa=sfa[rt];//不是SPFA,是special_father
access(spfa);
splay(spfa);
fc b=sum[spfa];
// X[x]=a.k * X[rt] + a.b
if (b.k==1)
return b.b?-1:-2;
if (b.k==0)
return a.calc(b.b);
// x*(b.k-1) + b.b = 0 (mod Mod)
// x = Inv(1-b.k) * b.b
return a.calc(Inv(1-b.k+Mod)*b.b%Mod);
}
int oncirclr(int x,int rt){
int f=sfa[rt];
if (x==f)
return 1;
access(f);
splay(f);
splay(x);
return !isroot(f);
}
void update(int x,int p,int k,int b){
access(x);
splay(x);
val[x]=fc(k,b);
pushup(x);
int rt=find(x);
if (x==rt){
int prt=find(p);
if (prt==rt)
sfa[x]=p;
else
sfa[x]=0,link(x,p);
}
else if (oncirclr(x,rt)){
cut(x);
link(rt,sfa[rt]);
sfa[rt]=0;
int prt=find(p);
if (prt==x)
sfa[x]=p;
else
link(x,p);
}
else {
cut(x);
int prt=find(p);
if (prt==x)
sfa[x]=p;
else
link(x,p);
}
}
int vis[N],in[N];
void dfs(int x){
in[x]=vis[x]=1;
int y=fa[x];
if (in[y]){
fa[x]=0;
sfa[x]=y;
}
if (!vis[y])
dfs(y);
in[x]=0;
}
int n,m;
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++){
int k,b;
scanf("%d%d%d",&k,&fa[i],&b);
val[i]=sum[i]=fc(k,b);
son[i][0]=son[i][1]=sfa[i]=0;
}
memset(vis,0,sizeof vis);
memset(in,0,sizeof in);
for (int i=1;i<=n;i++)
if (!vis[i])
dfs(i);
scanf("%d",&m);
for (int i=1;i<=m;i++){
char op[4];
scanf("%s",op);
if (op[0]=='A'){
int x;
scanf("%d",&x);
printf("%d\n",query(x));
}
else {
int x,y,k,b;
scanf("%d%d%d%d",&x,&k,&y,&b);
update(x,y,k,b);
}
}
return 0;
}

浙公网安备 33010602011771号