• 【NOIp2019模拟】T2—水题(LCT+斐波那契数列)


    传送门

    有换父亲,考虑用LCTLCT维护
    考虑利用斐波那契数列通项公式

    fi=(1+52)i(152)i5f_i=frac{(frac{1+sqrt 5}2)^i-(frac{1-sqrt5}2)^i}{sqrt 5}
    由于55在模998244353998244353下没有二次剩余
    考虑维护一个模意义下的虚数
    而且其实只用维护1+51+sqrt 5,另一半把虚部系数取反就是了
    发现操作四其实只需要维护前缀积的和,后缀积的和,所有子区间的积的和,区间积就可以维护了

    对于操作2,可以发现覆盖后那几个东西也都可以维护
    具体就是一个等比数列求和
    子区间的积的和就是等比数列求和后加起来再做一个等比数列求和就可以了

    还有就是求a+b5a+bsqrt 5这样一个东西的逆元
    (a25b2)=(a+b5)(ab5)(a^2-5b^2)=(a+bsqrt 5)(a-bsqrt 5),前面是一个实数就可以做了

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    const int mod=998244353;
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    inline void Add(int &a,int b){a=add(a,b);}
    inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
    inline void Dec(int &a,int b){a=dec(a,b);}
    inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
    inline void ex_gcd(int a,int b,int &x,int &y){
    	if(!b){x=1,y=0;return ;}ex_gcd(b,a%b,y,x);y-=a/b*x;
    }
    struct Map{
    	static cs int magic=1898579;
    	int key[magic],val[magic];
    	Map(){memset(key,-1,sizeof key);}
    	int locate(int k)cs{
    		int h=k%magic;
    		while(key[h]!=-1&&key[h]!=k)h=h+1==magic?0:h+1;
    		return h;
    	}
    	int &operator[](int k){
    		int h=locate(k);
    		if(key[h]==-1){
    			key[h]=k;val[h]=0;
    		}
    		return val[h];
    	}
    	bool count(int k)cs{return key[locate(k)]==k;}
    }iv;
    inline int Inv(int a){
    	if(!a)return 1;
    	if(iv.count(a))return iv[a];
    	int x,y;ex_gcd(a,mod,x,y);
    	return iv[a]=(x%mod+mod)%mod;
    }
    inline void chemx(int &a,int b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    cs int inv2=ksm(2,mod-2);
    struct plx{
    	int x,y;
    	plx(int _x=0,int _y=0):x(_x),y(_y){}
    	friend inline plx operator +(cs plx &a,cs plx &b){
    		return plx(add(a.x,b.x),add(a.y,b.y));
    	}
    	friend inline plx operator +(cs plx &a,cs int &b){
    		return plx(add(a.x,b),a.y);
    	}
    	friend inline plx operator -(cs plx &a,cs plx &b){
    		return plx(dec(a.x,b.x),dec(a.y,b.y));
    	}
    	friend inline plx operator -(cs plx &a,cs int &b){
    		return plx(dec(a.x,b),a.y);
    	}
    	friend inline plx operator *(cs plx &a,cs plx &b){
    		return plx((1ll*a.x*b.x+5ll*a.y*b.y)%mod,(1ll*a.x*b.y+1ll*a.y*b.x)%mod);
    	}
    	friend inline plx operator *(cs plx &a,cs int &b){
    		return plx(mul(a.x,b),mul(a.y,b));
    	}
    };
    cs plx bas=plx(inv2,inv2);
    inline plx ksm(plx a,int b){
    	plx res(1,0);
    	for(;b;b>>=1,a=a*a)if(b&1)res=res*a;
    	return res;
    }
    inline plx Inv(plx a){
    	return plx(a.x,mod-a.y)*Inv(((1ll*a.x*a.x-5ll*a.y*a.y)%mod+mod)%mod);
    }
    cs int N=100005;
    plx a[N];
    int n,m,fa[N];
    namespace Lct{
    	struct node{
    		plx v,pre,suf,s;
    		friend inline node operator *(cs node &a,cs node &b){
    			node c;
    			c.s=a.s+b.s+a.suf*b.pre;
    			c.pre=a.pre+a.v*b.pre;
    			c.suf=a.suf*b.v+b.suf;
    			c.v=a.v*b.v;
    			return c;
    		}
    	};
    	node val[N];
    	int fa[N],son[N][2],siz[N],rev[N],cov[N];
    	#define lc(u) son[u][0]
    	#define rc(u) son[u][1]
    	inline void initval(int u){
    		val[u].v=val[u].pre=val[u].suf=val[u].s=a[u],siz[u]=1;
    	}
    	inline void pushup(int u){
    		initval(u);
    		siz[u]=siz[lc(u)]+siz[rc(u)]+1;
    		if(lc(u))val[u]=val[lc(u)]*val[u];
    		if(rc(u))val[u]=val[u]*val[rc(u)];
    	}
    	inline void pushcov(int u,int k){
    		plx x=ksm(bas,k),iv=Inv(x-1);
    		a[u]=x,val[u].v=ksm(x,siz[u]);
    		val[u].pre=val[u].suf=(val[u].v*x-x)*iv;
    		val[u].s=((val[u].v*x*x-x*x)*iv-x*siz[u])*iv;
    		cov[u]=k;
    	}
    	inline void pushrev(int u){
    		swap(lc(u),rc(u));
    		swap(val[u].pre,val[u].suf),rev[u]^=1;
    	}
    	inline void pushdown(int u){
    		if(rev[u]){
    			if(lc(u))pushrev(lc(u));
    			if(rc(u))pushrev(rc(u));
    			rev[u]=0;
    		}
    		if(cov[u]){
    			if(lc(u))pushcov(lc(u),cov[u]);
    			if(rc(u))pushcov(rc(u),cov[u]);
    			cov[u]=0;
    		}
    	}
    	inline bool isrt(int u){
    		if(!fa[u])return 1;
    		return lc(fa[u])!=u&&rc(fa[u])!=u;
    	}
    	inline bool isrc(int u){
    		return rc(fa[u])==u;
    	}
    	inline void rotate(int v){
    		int u=fa[v],z=fa[u];
    		int t=rc(u)==v;
    		fa[v]=z;
    		if(!isrt(u))son[z][rc(z)==u]=v;
    		fa[son[v][t^1]]=u,son[u][t]=son[v][t^1];
    		son[v][t^1]=u,fa[u]=v;
    		pushup(u),pushup(v);
    	}
    	int stk[N],top;
    	inline void splay(int u){
    		stk[top=1]=u;
    		for(int v=u;!isrt(v);v=fa[v])stk[++top]=fa[v];
    		for(int i=top;i;i--)pushdown(stk[i]);
    		while(!isrt(u)){
    			if(!isrt(fa[u]))
    			isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
    			rotate(u);
    		}
    	}
    	inline void access(int u){
    		for(int v=0;u;v=u,u=fa[u]){
    			splay(u),rc(u)=v;
    			if(v)fa[v]=u;
    			pushup(u);
    		}
    	}
    	inline void makert(int u){
    		access(u),splay(u),pushrev(u);
    	}
    	inline void link(int u,int v){
    		makert(u),splay(v),fa[u]=v,pushup(v);
    	}
    	inline void cut(int u,int v){
    		makert(u),access(v),splay(v);
    		lc(v)=fa[u]=0;pushup(v);
    	}
    	inline int query(int u,int v){
    		makert(u);
    		access(v);
    		splay(v);
    		plx now=val[v].s;
    		return mul(2,now.y);
    	}
    	inline void cover(int u,int v,int k){
    		makert(u),access(v),splay(v);
    		pushcov(v,k);
    	}
    }
    int main(){
    	#ifdef Stargazer
    	freopen("lx.cpp","r",stdin);
    	#endif
    	n=read(),m=read();
    	for(int i=1;i<=n;i++){
    		int k=read();
    		a[i]=ksm(bas,k);
    		Lct::initval(i);
    	}
    	for(int i=2;i<=n;i++)Lct::fa[i]=fa[i]=read();
    	while(m--){
    		int op=read();
    		if(op==1){
    			int u=read(),v=read();
    			Lct::cut(u,fa[u]),Lct::link(u,v),fa[u]=v;
    		}
    		if(op==2){
    			int u=read(),v=read(),k=read();
    			Lct::cover(u,v,k);
    		}
    		if(op==3){
    			int u=read();
    			Lct::makert(u);plx now=a[u];
    			cout<<mul(2,now.y)<<'
    ';
    		}
    		if(op==4){
    			int u=read(),v=read();
    			cout<<Lct::query(u,v)<<'
    ';
    		}
    	}
    }
    
  • 相关阅读:
    mysql int类型 int(11) 和int(2)区别
    mysql 用户 登陆 权限相关
    【转】ext4+delalloc造成单次写延迟增加的分析
    write 系统调用耗时长的原因
    【转】通过blktrace, debugfs分析磁盘IO
    win7 wifi热点
    【SystemTap】 Linux下安装使用SystemTap源码安装SystemTap
    pdflush进程介绍与优化【转】
    How to find per-process I/O statistics on Linux
    oom_killer
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328586.html
Copyright © 2020-2023  润新知