zoukankan      html  css  js  c++  java
  • 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
    ",query(x));
    		}
    		else {
    			int x,y,k,b;
    			scanf("%d%d%d%d",&x,&k,&y,&b);
    			update(x,y,k,b);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    linux学习(三)输入输出重定向和管道功能、cat命令、more命令
    linux基础学习(二)ls命令以及文件访问权限例(-rw-r-r--)
    c语言的全排列
    linux基础学习(一)常用命令:date、pwd、cd、cal、who、wc等等
    用linux编译并运行c文件
    安装linux虚拟机
    安装quickLook插件以及解决如何不能读取offic问题
    java:数据结构(四)二叉查找树以及树的三种遍历
    java:数据结构复习(三)链表队列
    数据结构java学习(三)循环队列
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ2759.html
Copyright © 2011-2022 走看看