• 【CSP-S 2019模拟】T1 —看门人(长链剖分+线段树)


    传送门


    签到水题

    长剖维护一下,每次在链顶把链底向上一个个合并轻儿子
    用一颗线段树维护单点修改和区间询问即可

    考试的时候看错题了…
    以为只找向下一条路径
    还写了个线段树合并对拍了2h2h
    我是个瓜皮

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<22|5;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ib==ob)?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 re register
    #define cs const
    #define ll long long
    #define pb push_back
    #define poly vector<int>
    #define pii pair<int,int>
    #define fi first
    #define se second
    inline void chemx(ll &a,ll b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    cs int mod=998244353;
    inline int Add(int &a,int b){return (a+=b)>=mod?a-=mod:0;}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    cs int N=1000005;
    int n,m,pw[N];
    ll ans[N];
    vector<pii> e[N];
    vector<int> chain[N];
    int dep[N],mxdep[N],son[N],L[N],R[N],fa[N],top[N];
    ll dis[N];
    ll *f[N],tmp[N<<2],*id;
    void dfs1(int u){
    	for(int i=0;i<e[u].size();i++){
    		int v=e[u][i].fi;
    		dep[v]=dep[u]+1,dis[v]=dis[u]+e[u][i].se;
    		dfs1(v);
    		if(mxdep[v]>mxdep[son[u]])son[u]=v;
    	}
    	mxdep[u]=mxdep[son[u]]+1;
    }
    void dfs2(int u,int tp){
    	top[u]=tp;
    	if(son[u])dfs2(son[u],tp);
    	for(int i=0;i<e[u].size();i++){
    		int v=e[u][i].fi;
    		if(v==son[u])continue;
    		dfs2(v,v);
    	}
    	chain[top[u]].pb(u);
    }
    namespace Seg{
    	ll mx[N<<2],a[N];
    	int n;
    	#define lc (u<<1)
    	#define rc ((u<<1)|1)
    	#define mid ((l+r)>>1)
    	inline void pushup(int u){
    		mx[u]=max(mx[lc],mx[rc]);
    	}
    	void build(int u,int l,int r){
    		if(l==r){mx[u]=a[l];return;}
    		build(lc,l,mid),build(rc,mid+1,r);
    		pushup(u);
    	}
    	inline void init(int len,ll *f){
    		n=len-1;
    		for(int i=0;i<=n;i++)a[i]=f[i];
    		build(1,0,n);
    	}
    	void insert(int u,int l,int r,int p,ll k){
    		if(l==r){chemx(mx[u],k);return;}
    		if(p<=mid)insert(lc,l,mid,p,k);
    		else insert(rc,mid+1,r,p,k);
    		pushup(u);
    	}
    	inline void update(int p,ll k){
    		insert(1,0,n,p,k);
    	}
    	ll query(int u,int l,int r,int st,int des){
    		if(st>r||l>des)return -1;
    		if(st<=l&&r<=des)return mx[u];
    		ll res=-1;
    		if(st<=mid)chemx(res,query(lc,l,mid,st,des));
    		if(mid<des)chemx(res,query(rc,mid+1,r,st,des));
    		return res;
    	}
    	inline ll ask(int l,int r){
    		
    		ll res=query(1,0,n,l,r);
    		return res;
    	}
    	#undef lc 
    	#undef rc
    	#undef mid
    }
    inline ll Addchain(int u,int tt,int v){
    	ll res=-1;re int del=dep[v]-dep[u];
    	for(int i=0;i<mxdep[v];i++){
    		int l=dep[tt]-dep[u]+L[tt]-i-1,r=dep[tt]-dep[u]+R[tt]-i-1;
    		ll now=-1;
    		if(r>=dep[tt]-dep[u])now=Seg::ask(l,r);
    		if(now!=-1)chemx(res,f[v][i]+now);
    	}
    	for(re int i=0;i<mxdep[v];i++){
    		if(f[v][i]>f[u][del+i])f[u][del+i]=f[v][i],Seg::update(del+i,f[u][del+i]);
    	}
    	if(res!=-1)res-=2*dis[tt];
    	return res;
    }
    inline ll ask(int u,int v){
    	int del=dep[v]-dep[u];
    	ll res=Seg::ask(del+L[v],del+R[v]);
    	if(res!=-1)res-=dis[v];
    	return res;
    }
    inline void calc_ans(int u){
    	Seg::init(mxdep[u],f[u]);
    	for(re int i=0,v,j,t;i<chain[u].size();i++){
    		v=chain[u][i];
    		for(j=0;j<e[v].size();j++){
    			t=e[v][j].fi;
    			if(t==son[v])continue;
    			chemx(ans[v],Addchain(u,v,t));
    		}
    		chemx(ans[v],ask(u,v));
    	}
    }
    void dp(int u){
    	f[u][0]=dis[u];
    	if(son[u]){
    		f[son[u]]=f[u]+1,dp(son[u]);
    	}
    	for(re int i=0,v;i<e[u].size();i++){
    		v=e[u][i].fi;
    		if(v==son[u])continue;
    		f[v]=id,id+=mxdep[v];
    		dp(v);
    	}
    	if(u==top[u])calc_ans(u);
    }
    signed main(){
    	int size=100<<20;
        __asm__ ("movq %0,%%rsp
    "::"r"((char*)malloc(size)+size));//提交用这个 
    	n=read();memset(ans,-1,sizeof(ans));
    	for(int i=1;i<=n;i++)L[i]=read(),R[i]=read();
    	for(int i=2,w;i<=n;i++)
    		fa[i]=read(),w=read(),e[fa[i]].pb(pii(i,w));
    	dep[1]=pw[0]=1;
    	for(int i=1;i<=n;i++)pw[i]=mul(pw[i-1],23333);
    	dfs1(1),dfs2(1,1);
    	id=tmp,f[1]=id,id+=mxdep[1];
    	dp(1);int res=0;
    	for(int i=1;i<=n;i++)Add(res,mul(pw[n-i],(ans[i]%mod+mod)%mod));
    	cout<<res;exit(0);
    }
    
  • 相关阅读:
    LinkedList源码解析
    四种List实现类的对比总结
    HashMap源码解析
    Flutter——Switch组件(开关组件)
    Flutter——Radio组件、RadioListTile组件(单选按钮组件)
    Flutter——Checkbox组件、CheckboxListTile(多选框组件)
    Flutter——TextField组件(文本框组件)
    Flutter——FloatingActionButton组件(浮动按钮组件)
    Flutter中的按钮组件介绍
    Flutter——Drawer、DrawerHeader、UserAccountsDrawerHeader组件(侧边栏组件)
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328529.html
Copyright © 2020-2023  润新知