专项测试(数据结构1)

专项测试(数据结构1)

果然不出我所料,数据结构比后缀数组难

这个第二题的\(MLE\)完全不出我所料,考场上算着就一个\(G\)

所以我认为卡内存也是一个非常重要的东西

推式子的能力还是不行,第一题莫比乌斯大白板,美腿出来!!!

后来呢最后一题二分还没想出来。。。。

T1 Surprise me

CF原题,我没做过

推式子,看网上题解吧

最后用一个莫比乌斯反演,不是我学的那种,是换函数那种,我学的是合适变换

然后用虚树提点,做个\(DP\)就行了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const int mod=1e9+7;
const int N=2e5+5;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        y>>=1;x=x*x%mod;
    }
    return ret;
}
int n,a[N],ans,id[N];
int to[N*2],nxt[N*2],head[N],rp;
void add_edg(int x,int y){
    to[++rp]=y;
    nxt[rp]=head[x];
    head[x]=rp;
}
int son[N],siz[N],dep[N],fa[N];
int top[N],dfn[N],dd;
void dfs_fi(int x,int f){
    fa[x]=f;dep[x]=dep[f]+1;
    son[x]=0;siz[x]=1;
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==fa[x])continue;
        //dep[y]=dep[x]+1;
        dfs_fi(y,x);
        siz[x]+=siz[y];
        if(!son[x]||siz[y]>siz[son[x]])son[x]=y;
    }
}
void dfs_se(int x,int f){
    top[x]=f;dfn[x]=++dd;
    if(son[x])dfs_se(son[x],f);
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(y==son[x]||y==fa[x])continue;
        dfs_se(y,y);
    }
}
int LCA(int x,int y){
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        x=fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}
int p[N],pi[N],mu[N],cnt;
bool vip[N];
void xxs(){
    mu[1]=1;fo(i,2,n){
        if(!vip[i])p[++cnt]=i,pi[i]=i-1,mu[i]=-1;
        for(int j=1;j<=cnt&&p[j]*i<=n;j++){
            vip[i*p[j]]=true;
            if(i%p[j]==0){
                pi[i*p[j]]=pi[i]*p[j];
                mu[i*p[j]]=0;
                break;
            }
            pi[i*p[j]]=pi[i]*(p[j]-1);
            mu[i*p[j]]=-mu[i];
        }
    }
}
int f[N],g[N],dp[N],res,tes,sum;
int w[N],num;
int sta[N],tot;
bool vis[N];
bool com(int x,int y){return dfn[x]<dfn[y];}
void vtree(){
    sort(w+1,w+num+1,com);
    sta[tot=1]=1;head[1]=0;rp=0;
    fo(i,1,num){
        if(w[i]==1)continue;
        int lca=LCA(sta[tot],w[i]);
        if(lca!=sta[tot]){
            while(dfn[lca]<dfn[sta[tot-1]]){
                add_edg(sta[tot-1],sta[tot]);
                tot--;
            }
            if(lca!=sta[tot-1]){
                head[lca]=0;
                add_edg(lca,sta[tot]);
                sta[tot]=lca;
            }
            else add_edg(lca,sta[tot]),tot--;
        }
        head[w[i]]=0;sta[++tot]=w[i];
    }
    fo(i,1,tot-1)add_edg(sta[i],sta[i+1]);
}
void DP(int x){dp[x]=0;
    if(vis[x]){tes=(tes+2*pi[a[x]]*pi[a[x]]%mod*dep[x])%mod;dp[x]=pi[a[x]];}
    for(int i=head[x];i;i=nxt[i]){
        int y=to[i];DP(y);
        tes=(tes+4*dp[x]%mod*dp[y]%mod*dep[x]%mod)%mod;
        dp[x]=(dp[x]+dp[y])%mod;
    }
    // cout<<x<<" "<<tes<<endl;
}
signed main(){
    n=read();pi[1]=1;
    fo(i,1,n)a[i]=read(),id[a[i]]=i;
    fo(i,1,n-1){
        int x=read(),y=read();
        add_edg(x,y);
        add_edg(y,x);
    }
    dfs_fi(1,0);dfs_se(1,1);xxs();
    fo(i,1,n/2){
        num=res=tes=sum=0;
        for(int j=i;j<=n;j+=i){
            w[++num]=id[j];vis[id[j]]=true;
            res=(res+2*pi[j]*dep[id[j]]%mod)%mod;
            sum=(sum+pi[j])%mod;
        }
        vtree();dp[1]=0;DP(1);cout<<endl;
        res=res*sum%mod;g[i]=(res-tes+mod)%mod;
        // cout<<res<<" "<<tes<<" "<<g[i]<<endl;
        for(int j=i;j<=n;j+=i)vis[id[j]]=false;
    }
    fo(i,1,n/2)for(int j=i;j<=n;j+=i)f[i]=(f[i]+mu[j/i]*g[j]%mod+mod)%mod;
    fo(i,1,n/2)ans=(ans+f[i]*i%mod*ksm(pi[i],mod-2)%mod)%mod;
    ans=ans*ksm(n*(n-1)%mod,mod-2)%mod;
    printf("%lld",ans);
}

T2 神牛养成计划

两个\(trie\),一个正着,一个反着

再用个主席树判断子树交集,

考场上用了两个后缀自动机。。。。。

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const int N=2e6+5;
int rt[N];
struct ZXS{
    struct POT{
        int sum,ls,rs;
    }tr[2000*80];
    int seg;
    void ins(int pr,int &x,int l,int r,int pos){
        x=++seg;tr[x]=tr[pr];tr[x].sum++;
        // cout<<seg<<endl;
        if(l==r)return ;
        int mid=l+r>>1;
        if(pos<=mid)ins(tr[pr].ls,tr[x].ls,l,mid,pos);
        else ins(tr[pr].rs,tr[x].rs,mid+1,r,pos);
    }
    int query(int pr,int x,int l,int r,int ql,int qr){
        // cout<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<tr[x].sum<<" "<<tr[pr].sum<<endl;
        if(ql<=l&&r<=qr)return tr[x].sum-tr[pr].sum;
        int mid=l+r>>1,ret=0;
        if(ql<=mid)ret+=query(tr[pr].ls,tr[x].ls,l,mid,ql,qr);
        if(qr>mid)ret+=query(tr[pr].rs,tr[x].rs,mid+1,r,ql,qr);
        return ret;
    }
}zxs;
struct ACM{
    struct POT{
        int fail;
        vector<int> vec;
    }tr[N];
    int seg;
    int to[N],nxt[N],head[N],val[N],rp;
    void add_edg(int x,int y,int v){
        to[++rp]=y;val[rp]=v;
        nxt[rp]=head[x];
        head[x]=rp;
    }
    void ins(char *x,int id){
        int len=strlen(x+1);
        int now=0;
        fo(i,1,len){
            int fl=false;
            for(int j=head[now];j;j=nxt[j]){
                if(val[j]==x[i]-'a'){
                    now=to[j];fl=true;break;
                }
            }
            if(!fl){
                ++seg;add_edg(now,seg,x[i]-'a');
                now=seg;
            }
        }
        tr[now].vec.push_back(id);
    }
}z,f;
int dzn[N],dzm[N],cnz;
int dfn[N],dfm[N],cnf,idf[2005];
void dfs_f(int x){
    dfn[x]=++cnf;
    for(int i:f.tr[x].vec)idf[i]=cnf;
    for(int i=f.head[x];i;i=f.nxt[i]){
        int y=f.to[i];
        dfs_f(y);
    }
    dfm[x]=cnf;
}
void dfs_z(int x){
    dzn[x]=++cnz;rt[cnz]=rt[cnz-1];
    for(int i:z.tr[x].vec)zxs.ins(rt[cnz],rt[cnz],1,cnf,idf[i]);
    for(int i=z.head[x];i;i=z.nxt[i]){
        int y=z.to[i];
        dfs_z(y);
    }
    dzm[x]=cnz;
}
int n,m,ans;
char s[N],t[N];
signed main(){
    // cerr<<(sizeof(z)*2>>20)<<endl;
    n=read();
    fo(i,1,n){
        scanf("%s",s+1);
        z.ins(s,i);
        reverse(s+1,s+strlen(s+1)+1);
        f.ins(s,i);
    }
    dfs_f(0);dfs_z(0);
    m=read();
    while(m--){
        int ls,lt;
        scanf("%s",s+1);ls=strlen(s+1);
        scanf("%s",t+1);lt=strlen(t+1);
        fo(i,1,ls)s[i]=(s[i]-'a'+ans)%26+'a';
        fo(i,1,lt)t[i]=(t[i]-'a'+ans)%26+'a';
        reverse(t+1,t+lt+1);bool fl=true;
        int nz=0;fo(i,1,ls){
            int fla=false;
            for(int j=z.head[nz];j;j=z.nxt[j]){
                if(z.val[j]==s[i]-'a'){
                    nz=z.to[j];fla=true;break;
                }
            }
            if(!fla){fl=false;break;}
        }
        int nf=0;fo(i,1,lt){
            int fla=false;
            for(int j=f.head[nf];j;j=f.nxt[j]){
                if(f.val[j]==t[i]-'a'){
                    nf=f.to[j];fla=true;break;
                }
            }
            if(!fla){fl=false;break;}
        }
        if(!fl){printf("%d\n",ans=0);continue;}
        printf("%d\n",ans=zxs.query(rt[dzn[nz]-1],rt[dzm[nz]],1,cnf,dfn[nf],dfm[nf]));
    }
}

发现\(K\)可以放到复杂度中,于是我们直接用主席树维护最大最小值

然后用一个优先队列,不断弹出就好了

然后我就写了一个带\(pushdown\)的主席树,内存炸了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+5;
int n,k,a[N],rt[N];
struct ZXS{
    struct POT{
        int mx,id,tg,ls,rs;
    }tr[N*150];
    int seg,mxn,idn;
    int newpot(int x){
        ++seg;tr[seg]=tr[x];
        return seg;
    }
    void pushup(int x){
        if(tr[tr[x].ls].mx>tr[tr[x].rs].mx){
            tr[x].mx=tr[tr[x].ls].mx;
            tr[x].id=tr[tr[x].ls].id;
        }
        else {
            tr[x].mx=tr[tr[x].rs].mx;
            tr[x].id=tr[tr[x].rs].id;
        }
        return ;
    }
    void pushdown(int x){
        tr[x].ls=newpot(tr[x].ls);
        tr[x].rs=newpot(tr[x].rs);
        tr[tr[x].ls].tg+=tr[x].tg;
        tr[tr[x].ls].mx+=tr[x].tg;
        tr[tr[x].rs].tg+=tr[x].tg;
        tr[tr[x].rs].mx+=tr[x].tg;
        // cout<<tr[tr[x].ls].tg<<" "<<tr[tr[x].rs].tg<<endl;
        tr[x].tg=0;
    }
    void build(int &x,int l,int r){
        x=++seg;tr[x].id=l;
        if(l==r)return ;
        int mid=l+r>>1;
        build(tr[x].ls,l,mid);
        build(tr[x].rs,mid+1,r);
    }
    void ins(int &x,int l,int r,int ql,int qr,int v){
        x=newpot(x);// if(v==1)cout<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<tr[x].mx<<" "<<tr[x].tg<<endl;
        if(ql<=l&&r<=qr){
            tr[x].tg+=v;tr[x].mx+=v;
            return ;
        }
        if(tr[x].tg)pushdown(x);
        int mid=l+r>>1;
        if(ql<=mid)ins(tr[x].ls,l,mid,ql,qr,v);
        if(qr>mid)ins(tr[x].rs,mid+1,r,ql,qr,v);
        pushup(x);return ;
    }
    void query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){
            if(tr[x].mx>mxn)mxn=tr[x].mx,idn=tr[x].id;
            return ;
        }
        if(tr[x].tg)pushdown(x);
        int mid=l+r>>1;
        if(ql<=mid)query(tr[x].ls,l,mid,ql,qr);
        if(qr>mid)query(tr[x].rs,mid+1,r,ql,qr);
        pushup(x);
    }
}zxs;
struct node{
    int l,r,v;
    bool operator < (node a)const{
        return v<a.v;
    }
};
priority_queue<node> q;
map<int,int> mp;
int lst[N];
signed main(){
    n=read();k=read();
    zxs.build(rt[0],1,n);
    fo(i,1,n){
        a[i]=read();
        if(mp.find(a[i])!=mp.end())lst[i]=mp[a[i]];
        mp[a[i]]=i;rt[i]=zxs.newpot(rt[i-1]);
        zxs.ins(rt[i],1,n,lst[i]+1,i,a[i]);
        zxs.mxn=-inf;zxs.query(rt[i],1,n,1,i);
        q.push(node{zxs.idn,i,zxs.mxn});
    }
    // zxs.mxn=-inf;zxs.query(rt[6],1,n,4,4);
    while(--k){
        node now=q.top();q.pop();
        zxs.ins(rt[now.r],1,n,now.l,now.l,-inf-now.v);
        zxs.mxn=-inf;zxs.query(rt[now.r],1,n,1,now.r);
        if(zxs.mxn!=inf)q.push(node{zxs.idn,now.r,zxs.mxn});
    }
    printf("%lld\n",q.top().v);
}

这个是没有\(pushdown\)

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')t=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*t;
}
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=1e5+5;
int n,k,a[N],rt[N];
struct ZXS{
    struct POT{
        ll mx,tg;
        int id,ls,rs;
    }tr[N*75];
    int seg,idn;ll mxn;
    int newpot(int x){
        ++seg;tr[seg]=tr[x];
        return seg;
    }
    void pushup(int x){
        if(tr[tr[x].ls].mx>tr[tr[x].rs].mx){
            tr[x].mx=tr[tr[x].ls].mx+tr[x].tg;
            tr[x].id=tr[tr[x].ls].id;
        }
        else {
            tr[x].mx=tr[tr[x].rs].mx+tr[x].tg;
            tr[x].id=tr[tr[x].rs].id;
        }
        return ;
    }
    void build(int &x,int l,int r){
        x=++seg;tr[x].id=l;
        if(l==r)return ;
        int mid=l+r>>1;
        build(tr[x].ls,l,mid);
        build(tr[x].rs,mid+1,r);
    }
    void ins(int &x,int l,int r,int ql,int qr,ll v){
        x=newpot(x);
        if(ql<=l&&r<=qr){
            tr[x].tg+=v;tr[x].mx+=v;
            return ;
        }
        int mid=l+r>>1;
        if(ql<=mid)ins(tr[x].ls,l,mid,ql,qr,v);
        if(qr>mid)ins(tr[x].rs,mid+1,r,ql,qr,v);
        pushup(x);return ;
    }
    void query(int x,int l,int r,int ql,int qr,ll sum){
        if(ql<=l&&r<=qr){
            if(tr[x].mx+sum>mxn)mxn=tr[x].mx+sum,idn=tr[x].id;
            return ;
        }
        int mid=l+r>>1;
        if(ql<=mid)query(tr[x].ls,l,mid,ql,qr,sum+tr[x].tg);
        if(qr>mid)query(tr[x].rs,mid+1,r,ql,qr,sum+tr[x].tg);
        pushup(x);
    }
}zxs;
struct node{
    int l,r;ll v;
    bool operator < (node a)const{
        return v<a.v;
    }
};
priority_queue<node> q;
map<ll,int> mp;
int lst[N];
signed main(){
    n=read();k=read();
    zxs.build(rt[0],1,n);
    fo(i,1,n){
        a[i]=read();
        if(mp.find(a[i])!=mp.end())lst[i]=mp[a[i]];
        mp[a[i]]=i;rt[i]=rt[i-1];
        zxs.ins(rt[i],1,n,lst[i]+1,i,a[i]);
        zxs.mxn=-inf;zxs.query(rt[i],1,n,1,i,0);
        q.push(node{zxs.idn,i,zxs.mxn});
    }
    while(--k){
        node now=q.top();q.pop();
        zxs.ins(rt[now.r],1,n,now.l,now.l,-inf-now.v);
        zxs.mxn=-inf;zxs.query(rt[now.r],1,n,1,now.r,0);
        if(zxs.mxn!=inf)q.push(node{zxs.idn,now.r,zxs.mxn});
    }
    printf("%lld\n",q.top().v);
}
posted @ 2021-12-18 20:12  fengwu2005  阅读(63)  评论(0编辑  收藏  举报