3020年牛客NOIP集训营

只拿了20分,T1 签到多测没清空+条件想到了忘写了;T2 50tps暴力因为队列访问空炸了;T4暴力没写完
其实凭实力可以拿到100+50+10+40分,很高了,但是就是不在状态
调整状态!踏实做题!力求高分!

[双向链表]T2:给出n种球和n个柱形容器,有3种操作,【1】x,y,z:把x个y球放进z号柱子【2】x,y:把x个球从顶部拿出y号柱子【3】x,y:把x柱子里的球顺次放入y。对于【2】操作,输出最后一个拿出的球的编号。(n<=5e5)

考场

首先是不可抑制的暴力思维:直接vector模拟,加了2个优化,一个是合并同类,一个是不关心未询问的柱子,但是没什么用。
然后想到链表维护操作,但是不知道【3】操作怎么转换链表方向(nxt/pre?),放弃了

正解

链表的加入类似建图的过程,维护head和2个方向,不用关注2个方向的指针种类,只要朝着走向走就可以(now=son[0]-->go[1]/ now=son[1]-->go[0]),对于最棘手的【3】,可以直接把head的x和y拼接,使heady指向tailx

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define rint register int 
#define ll long long
#define ull unsigned long long
#define chu printf
inline ll re()
{
    ll x=0,h=1;char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=3e5+100;
struct buf
{
    int cor,cnt,ch[2];
}e[N];
int h[N],t[N],n,m,tot;
int main()
{
   // freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    freopen("color.in","r",stdin);
    freopen("color.out","w",stdout);
    n=re(),m=re();
    for(rint i=1;i<=m;++i)
    {
        char s[6];
        scanf("%s",s+1);
        int x=re(),y=re(),z;
        if(s[3]=='s')
        {
            z=re();
            e[++tot]=(buf){y,x,h[z],0};
            if(h[z])
            {
                e[h[z]].ch[0]?(e[h[z]].ch[1]=tot):(e[h[z]].ch[0]=tot);
            }
            else t[z]=tot;
            h[z]=tot;
        }
        else if(s[3]=='p')
        {
            while(e[h[y]].cnt<x)
            {
                x-=e[h[y]].cnt;//删除y
                int lch=e[h[y]].ch[0]|e[h[y]].ch[1];
                (e[lch].ch[0]==h[y])?(e[lch].ch[0]=0):(e[lch].ch[1]=0);
                h[y]=lch;
            }
            e[h[y]].cnt-=x;
            chu("%d\n",e[h[y]].cor);
        }
        else
        {
            if(!h[x])continue;
            if(h[y])
            {
                e[h[y]].ch[0]?e[h[y]].ch[1]=h[x]:e[h[y]].ch[0]=h[x];
                e[h[x]].ch[0]?e[h[x]].ch[1]=h[y]:e[h[x]].ch[0]=h[y];
            }
            else t[y]=h[x];
            h[y]=t[x];
            h[x]=t[x]=0;
        }
    }
    return 0;

}
/*
3 5
push 1 1 1
push 1 2 1
push 2 3 2
put 1 2
pop 2 2

*/

[字符串匹配+局部处理思想]T4:定义偶数串是length是偶数,且满足结构AA的串,给出一个长度是n的偶数串,你可以进行若干次操作使得最终偶数串长度>=m,要求每次变换新增串最少,给出q次询问[l,r],询问区间的十进制数字%998244353的结果。(n<=1e5,m<=1e18)

考场

10pts
枚举相同后缀
40tps
kmp线性更新nxt,预处理串的[l,r]表示

正解

定义u=vv,w是v的前缀,满足v-w是v的前缀。
如果\(len_w|len_v\),偶串形态:\(vwwwwwwww\)
否则定义\(v0=w,v1=v,vi=v_{i-1}+v_{i-2}\),一直构造下去一定合法,
所以预处理每个v,直到长度>=m(最多logn个),询问只需维护前缀答案拼凑,维护时因为fib数列可拼凑,所以最后剩下的项<=length,直接散块累加,发i西安对于【1】情况这么干不影响答案。
\(O(q*logn+logn^2)\)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define rint register int 
#define ll long long
#define ull unsigned long long
#define chu printf
inline ll re()
{
    ll x=0,h=1;char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
const int N=120;
const int mod=998244353;//mod
ll h[100000+100];int nxt[100000+100];
ll l[120],f[120],rt[120];int n,q,mx;
ll m;
char s[100000+100];
inline ll qpow(ll a,ll b)
{
    ll c=1;
    while(b)
    {
        if(b&1)c=c*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return c;
}
inline ll get(ll go)
{
    ll sg=0;ll ans=0;
    for(rint i=mx;i>=0;--i)
    {
        if(sg+l[i]<=go)
        {
            sg+=l[i];
            ans=(ans*rt[i]%mod+f[i])%mod;
        }
    }
    ans=(ans*qpow(10,go-sg)%mod+h[go-sg])%mod;
    return ans;
}
inline void solve()
{
    scanf("%s",s+1);
    m=re(),q=re();
    n=strlen(s+1)/2;
    for(rint i=2;i<=n;++i)
    {
        int j=nxt[i-1];
        while(j&&s[j+1]!=s[i])j=nxt[j];
        if(s[j+1]==s[i])nxt[i]=j+1;
        else nxt[i]=0;
    }
    for(rint i=1;i<=n;++i)h[i]=(h[i-1]*10ll%mod+s[i]-'0');
    l[0]=n-nxt[n],f[0]=h[l[0]];rt[0]=qpow(10,l[0]);//意识到不对劲
    l[1]=n,f[1]=h[l[1]],rt[1]=qpow(10,l[1]);
    for(rint i=2;i<=100;++i)
    {
        l[i]=l[i-1]+l[i-2];
        f[i]=(1ll*f[i-1]*rt[i-2]%mod+f[i-2])%mod;
        rt[i]=qpow(10,l[i]);
        if(l[i]>=m){mx=i;break;}
    }
    for(rint i=1;i<=q;++i)
    {
        ll let=re(),ret=re();
        ll ans=get(ret)-get(let-1)*qpow(10,ret-let+1)%mod+mod;
        ans%=mod;
        chu("%lld\n",ans);
    }
}
int main()
{
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    freopen("even.in","r",stdin);
    freopen("even.out","w",stdout);
    int T=re();
    while(T--)solve();
    return 0;

}
/*
*/
posted on 2022-11-02 16:59  HZOI-曹蓉  阅读(12)  评论(0编辑  收藏  举报