zoukankan      html  css  js  c++  java
  • 联考20200801 T2 皮卡丘




    分析:
    整体思路是,没有被走到的点我们直接数学计算,走到的点暴力维护
    考虑对每次探索操作维护二叉树,由于每个点在没有被删的情况下为自然生长,其出现时间就是它的深度,而被炸掉的点会在目前时间的下一刻长出来
    我们在被炸掉的点上打上时间标记,表示这个点多久后才会长出来
    每次向下探索时,维护路径上的时间差(这个点长出来的时间减去这个点本应长出来的时间),用于统计子树内因删除而没有长出来的节点
    维护全局变量(Sz)(Lf)表示总节点数和叶子个数,生长时通过数学计算更新,删除时在建出来的二叉树上寻找删除的大小来更新
    总时间复杂度为(O(n+sum|S|))

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    #define maxn 1000005
    #define MOD 998244353
    #define inv2 499122177
    
    using namespace std;
    
    inline long long getint()
    {
    	long long num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,Tim;
    int pw[maxn];
    int ch[maxn][2],tim[maxn],tot;
    int Lf,Sz,wp,wl,L;
    char op[maxn];
    
    inline void update(int &u,int p,int ldt)
    {
    	if(!u)
    	{
    		if(Tim-ldt-p+1>=0)wp=(wp+pw[Tim-ldt-p+1]-1)%MOD;
    		if(Tim-ldt-p>=0)wl=(wl+pw[Tim-ldt-p])%MOD;
    		return;
    	}
    	if(Tim-ldt-p>0)wp++;
    	if(tim[u]!=-1)ldt=max(ldt,tim[u]-p);
    	update(ch[u][0],p+1,ldt),update(ch[u][1],p+1,ldt);
    	u=0;
    }
    
    inline void dfs(int u,int p,int ldt)
    {
    	if(tim[u]!=-1)ldt=max(ldt,tim[u]-p);
    	if(p==L)
    	{
    		wp=wl=0;
    		if(Tim-ldt-p<=0)wl=1;
    		update(ch[u][0],p+1,ldt),update(ch[u][1],p+1,ldt);
    		Sz=(Sz-wp-1)%MOD;
    		Lf=(Lf-wl+inv2)%MOD;
    		tim[u]=Tim+1;
    		return;
    	}
    	int d=(op[p]=='R');
    	if(!ch[u][d])ch[u][d]=++tot,tim[ch[u][d]]=-1,ch[tot][0]=ch[tot][1]=0;
    	dfs(ch[u][d],p+1,ldt);
    }
    
    int main()
    {
    	freopen("pikachu.in","r",stdin);
    	freopen("pikachu.out","w",stdout);
    
    	int T=getint();
    	pw[0]=1;
    	for(int i=1;i<maxn;i++)pw[i]=2*pw[i-1]%MOD;
    	memset(tim,-1,sizeof tim);
    	while(T--)
    	{
    		n=getint();
    		Lf=Sz=1,tot=Tim=0;
    		ch[0][0]=ch[0][1]=0;
    		while(n--)
    		{
    			scanf("%s",op);
    			if(op[0]=='G')
    			{
    				int x=getint();
    				Tim+=x;
    				Sz=(Sz+1ll*Lf*(pw[x+1]-2))%MOD;
    				Lf=1ll*Lf*pw[x]%MOD;
    			}
    			else scanf("%s",op),L=strlen(op),dfs(0,0,0);
    			printf("%d
    ",(Sz+MOD)%MOD);
    		}
    	}
    }
    

  • 相关阅读:
    通过注册表设置指定用户启动项的权限
    音频知识学习
    回老家也不忘老本......
    探索DOMNode
    表单填写示例(通过JavaScript访问DOM)
    最近的一些感悟
    C#和Java中的Substring()
    验证ASP.NET页生命周期时间的触发顺序
    解析c语言背后的汇编代码
    oracle nvl()函数在使用中出现的问题
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13422987.html
Copyright © 2011-2022 走看看