bzoj4943 uoj315 [Noi2017]蚯蚓

http://www.elijahqi.win/archives/3891
题面:http://uoj.ac/problem/315

正解 hash表模数参考了gxz巨佬的

正解就是在暴力的基础上发现我们只需要一开始提前把需要询问的串放入hash表 即可

这样hash表的总数不会太大 因为其他的字符串都不会出现在询问中

这题是复杂度分析的问题 考虑假如没有 2操作那么复杂度是稳的n*k问题就在于我每次分开之后会产生c*k^2的复杂度再次合并的时候也仅仅会产生c*k^2的复杂度

所以暴力也可以拿到很多的分

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int mod=998244353;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int N=5e5+10;
const int S=1e7+10;
const int g1=1117;
int n,m,cnt;ull p1[N];char s2[S];
inline int reads(){
    char ch=gc();while(!isdigit(ch)) ch=gc();int op=0;
    while(isdigit(ch)) ++op,s2[++cnt]=ch,ch=gc();return op;
}
struct node{
    int pre,nxt,nm;
}data[N];
struct node1{
    int op,x,y,to;
}qr[N];
namespace hst{
    const int mod=10233333;int h[mod];
    struct node{
        ull s;int nm,next;
    }data[20000010];
    int num;
    inline void init(ull s){
        int x=s%mod;
        for (int i=h[x];i;i=data[i].next){
            if (data[i].s==s) return;
        }
        data[++num].next=h[x];data[num].s=s;h[x]=num;
    }
    inline void insert1(ull s){
        int x=s%mod;
        for (int i=h[x];i;i=data[i].next)
            if (data[i].s==s){++data[i].nm;return;}
    }
    inline void del1(ull s){
        int x=s%mod;
        for (int i=h[x];i;i=data[i].next)
            if (data[i].s==s){--data[i].nm;return;}
    }
    inline int query(ull s){
        int x=s%mod;
        for (int i=h[x];i;i=data[i].next){
            if (data[i].s==s){return data[i].nm;}
        }return 0;
    }
}
int main(){
    freopen("b.in","r",stdin);
    n=read();m=read();int k=50;p1[0]=1;
    for (int i=1;i<=55;++i) p1[i]=p1[i-1]*g1;
    for (int i=1;i<=n;++i) {
        int s1=read();data[i].pre=data[i].nxt=i;data[i].nm=s1;
    }
    for (int owo=1;owo<=m;++owo){
        int op=read();qr[owo].op=op;
        if (op==1) qr[owo].x=read(),qr[owo].y=read();
        if (op==2) qr[owo].x=read();
        if (op==3){
            int lst=cnt;qr[owo].y=lst;
            int nn=reads();int kk=read();qr[owo].x=kk;qr[owo].to=cnt;
            ull hs1=0;
            for (int i=lst+1;i<=lst+kk;++i){
                hs1=hs1*g1+s2[i]-'0';
            }hst::init(hs1);
            for (int i=lst+kk+1;i<=cnt;++i){
                hs1=hs1-p1[kk-1]*(s2[i-kk]-'0');
                hs1=hs1*g1+s2[i]-'0';
                hst::init(hs1);
            }
        }
    }
    for (int i=1;i<=n;++i){
        int s1=data[i].nm;hst::insert1(s1);
    }
    for (int owo=1;owo<=m;++owo){
        int op=qr[owo].op;
        if (op==1){
            int x=qr[owo].x,y=qr[owo].y,lst=x;
            data[y].pre=x;data[x].nxt=y;int cnt=1;
            while(cnt<k){
                int tot=1,now=lst;ull hs1=0;
                hs1+=data[lst].nm;now=data[now].nxt;
                while(tot<k){++tot;
                    hs1=hs1*g1+data[now].nm;
                    if (tot>cnt) hst::insert1(hs1);
                    if (data[now].nxt==now) break;
                    now=data[now].nxt;
                }
                if(lst==data[lst].pre) break;
                lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
            }
        }
        if (op==2){
            int id=qr[owo].x,nxt=data[id].nxt;//puts("--");
            data[nxt].pre=nxt;
            int cnt=1,lst=id;
            while(cnt<k){
                int tot=1,now=lst;ull hs1=0;
                hs1+=data[lst].nm;now=data[now].nxt;
                while(tot<k){++tot;
                    hs1=hs1*g1+data[now].nm;
                    if(tot>cnt) hst::del1(hs1);
                    if (data[now].nxt==now) break;
                    now=data[now].nxt;
                }
                if (lst==data[lst].pre) break;
                lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
            }
            data[id].nxt=id;
        }
        if (op==3){
            int lst=qr[owo].y;int kk=qr[owo].x;int to=qr[owo].to;
            ull hs1=0;
            for (int i=lst+1;i<=lst+kk;++i){
                hs1=hs1*g1+s2[i]-'0';
            }ll ans=1;
            ans=ans*hst::query(hs1)%mod;
            for (int i=lst+kk+1;i<=to;++i){
                hs1=hs1-p1[kk-1]*(s2[i-kk]-'0');
                hs1=hs1*g1+s2[i]-'0';
                ans=ans*hst::query(hs1)%mod;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

我的第一发暴力:

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=998244353;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int N=5e5+10;
const int S=1e7+10;
const int g=1113;
const int g1=1117;
const int hsmod1=998244353;
const int hsmod=1e9+7;
int n,m;ll p[N],p1[N];char s1[2],s2[S];
struct node{
    int pre,nxt,nm;
}data[N];
namespace hst{
    const int mod=100003;int h[55][mod],num[55];
    struct node{
        int s,nm,next;
    }data[51][500001];
    inline void insert1(int s,int s1,int k){
        int x=s%mod;//printf("%d\n",s);
        for (int i=h[k][x];i;i=data[k][i].next){
            if (data[k][i].s==s1){
                ++data[k][i].nm;return;
            }
        }
        data[k][++num[k]].next=h[k][x];data[k][num[k]].nm=1;data[k][num[k]].s=s1;
        h[k][x]=num[k];
    }
    inline void del1(int s,int s1,int k){
        int x=s%mod;//printf("%d\n",s);
        for (int i=h[k][x];i;i=data[k][i].next){
            if (data[k][i].s==s1){
                --data[k][i].nm;return;
            }
        }
    }
    inline int query(int s,int s1,int k){
        int x=s%mod;//printf("%d\n",s);
        for (int i=h[k][x];i;i=data[k][i].next){
            if (data[k][i].s==s1){
                return data[k][i].nm;
            }
        }return 0;
    }
}
int main(){
    //freopen("b.in","r",stdin);
    n=read();m=read();p[0]=1;int k=50;p1[0]=1;
    for (int i=1;i<=n;++i) p[i]=p[i-1]*g%hsmod;
    for (int i=1;i<=n;++i) p1[i]=p1[i-1]*g1%hsmod1;
    for (int i=1;i<=n;++i) {
        scanf("%s",s1);data[i].pre=data[i].nxt=i;
        data[i].nm=s1[0]-'0';hst::insert1(s1[0]-'0',s1[0]-'0',1);
    }//int fd=0;
    for (int owo=1;owo<=m;++owo){
        int op=read();
        if (op==1){
            int x=read(),y=read(),lst=x;
            data[y].pre=x;data[x].nxt=y;int cnt=1;
            while(cnt<k){
                int tot=1,now=lst;ll hs=0,hs1=0;
                hs+=data[lst].nm;now=data[now].nxt;hs1=hs;
                while(tot<k){++tot;
                    hs=(hs*g+data[now].nm)%hsmod;
                    hs1=(hs1*g1+data[now].nm)%hsmod1;
                    if (tot>cnt) hst::insert1(hs,hs1,tot);
                    if (data[now].nxt==now) break;
                    now=data[now].nxt;
                }
                if(lst==data[lst].pre) break;
                lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
            }
        }
        if (op==2){
            int id=read(),nxt=data[id].nxt;//puts("--");
            data[nxt].pre=nxt;
            int cnt=1,lst=id;
            while(cnt<k){
                int tot=1,now=lst;ll hs=0,hs1=0;
                hs+=data[lst].nm;now=data[now].nxt;hs1=hs;
                while(tot<k){++tot;
                    hs=(hs*g+data[now].nm)%hsmod;
                    hs1=(hs1*g1+data[now].nm)%hsmod1;
                    if(tot>cnt) hst::del1(hs,hs1,tot);
                    if (data[now].nxt==now) break;
                    now=data[now].nxt;
                }
                if (lst==data[lst].pre) break;
                lst=data[lst].pre;++cnt;//printf("%d\n",cnt);
            }
            data[id].nxt=id;
        }
        if (op==3){
            //++fd;
            scanf("%s",s2+1);int kk=read();

            ll hs=0,hs1=0;
            //printf("%s\n",s2+1);int nn=strlen(s2+1);
            for (int i=1;i<=kk;++i){
                hs=(hs*g+s2[i]-'0')%hsmod;
                hs1=(hs1*g1+s2[i]-'0')%hsmod1;
            }ll ans=1;
            ans=ans*hst::query(hs,hs1,kk)%mod;
            for (int i=kk+1;s2[i];++i){
                hs=((hs-p[kk-1]*(s2[i-kk]-'0')%hsmod)%hsmod+hsmod)%hsmod;
                hs=(hs*g+s2[i]-'0')%hsmod;
                hs1=((hs1-p1[kk-1]*(s2[i-kk]-'0')%hsmod1)%hsmod1+hsmod1)%hsmod1;
                hs1=(hs1*g1+s2[i]-'0')%hsmod1;
                ans=ans*hst::query(hs,hs1,kk)%mod;
            }
            printf("%lld\n",ans);
            //if(fd==249) {printf("%s\n",s2+1);printf("%d\n",kk);return 0;}
        }
        //for (int i=1;i<=50;++i) printf("%d ",hst::num[i]);puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值