20191009

前言

  • B组题竟然没炸,开心= =
  • 主要是考完就放假心态很好。
  • 然而T1打挂了233。
  • 继续努力。

T1

  • 正解神仙矩阵快速幂。
  • 然而好像都是把周期循环周期长度次,这样可以保证正确。
  • 代码很短。主要是这个题值域很小,所以最长不下降子序列的暴力复杂度$\Theta(N^2)$变为了$\Theta(150N)$,没必要打线段树或树状数组。
  • 时间复杂度$\Theta(150len^2)$,空间复杂度$\Theta(len^2)$,len是周期长度的平方。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int const N=155;
ll n,ans;
int t,A,B,C,D,st,lit,zc;
int a[110000],vis[N],bar[N];
int main(){
    scanf("%lld%d%d%d%d%d",&n,&t,&A,&B,&C,&D);
    const int mod=D;
    for(register int i=1;i<=n;++i){
        if(vis[a[i]=t]){st=vis[t];lit=i-1;zc=i-vis[t];break;}
        vis[t]=i,t=(A*t*t+B*t+C)%mod;
    }
    if(!st)st=n+1;
    lit=min(n,1ll*lit+zc*zc);
    for(register int i=st+zc;i<=lit;++i)a[i]=a[i-zc];
    for(register int i=1,z,lt;i<st;++i){
        z=0,lt=a[i];
        for(register int j=0;j<=lt;++j)z=max(z,bar[j]);
        bar[lt]=++z,ans=max(ans,1ll*z);
    }
    for(register int i=st,z,lt;i<=lit;++i){
        z=0,lt=a[i];
        for(register int j=0;j<=lt;++j)z=max(z,bar[j]);
        bar[lt]=++z,ans=max(ans,(n-i)/zc+z);
    }
    printf("%lld",ans);
    return 0;
}
View Code

T2

  • 正解神仙DP,稍不会。
  • 向zzn大神学习了同余系最短路。
  • 找出最小的体积,设为V。
  • 那么V的倍数肯定可以凑出,我们只需考虑凑出小于V的V种情况所需要的最小体积即可。
  • spfa跑最短路。注意需要满足题目中的限制。
  • 时间复杂度上界$\Theta(kV^2)$,但实际远远达不到这个上界。
    空间复杂度$\Theta(kV)$。
  • 其中k是spfa的常数。
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
int const N=1e4;
int n,tot,m,l,c,mod=N,lit;
int a[101];
ll f[N];
int lm[N];
bool v[N];
int q[10000000],t=1,u,x;
template<class T>
inline T read(){
    T ss(0);char bb(getchar());
    while(bb<48||bb>57)bb=getchar();
    while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss;
}
inline int min(int x,int y){
    return x<y?x:y;
}
int main(){
    n=read<int>(),m=read<int>();
    for(register int i=1;i<=n;++i)mod=min(mod,a[i]=read<int>());
    const int MOD=mod;
    l=read<int>(),c=read<int>();
    std::sort(a+1,a+n+1);
    for(register int i=1;i<=n;++i)
        if(a[i]!=a[i-1])a[++tot]=a[i];
    n=tot;
    for(lit=1;lit<=n&&a[lit]<l;++lit);--lit;
    memset(f,0x3f,MOD<<3),memset(lm,0x3f,MOD<<2);
    f[0]=lm[0]=0;
    while(u^t){
        v[x=q[++u]]=0;
        ll bs=f[x];
        for(register int i=1,y,la=lm[x],lnow=la+1,lt=min(n,c==lm[x]?lit:n);i<=lt;++i){
            y=(x+a[i])%MOD;
            if(f[y]>bs+a[i]){
                f[y]=bs+a[i];
                if(i>lit)lm[y]=lnow;
                if(!v[y])v[q[++t]=y]=1;
            }
            else if(f[y]==bs+a[i]){
                if(i>lit && lm[y]>lnow){
                    lm[y]=lnow;
                    if(!v[y])v[q[++t]=y]=1;
                    continue;
                }
                else if(i<=lit && lm[y]>=lnow){
                    lm[y]=la;
                    if(!v[y])v[q[++t]=y]=1;
                }
            }
        }
    }
    while(m--){
        ll w=read<ll>();
        puts(f[w%MOD]<=w?"Yes":"No");
    }
    return 0;
}
View Code

T3

  • 本场考试最简单的题目竟然在T3……
  • 线段树维护dfs序即可。
  • 更新时向上标记。如果当前点在之前被更新过直接停止,这样保证每个点只被更新一次。
  • 然后这个题就没了。
  • 时间复杂度$\Theta(NlogN)$,空间复杂度$\Theta(N)$。
  • 但考试的时候我却打了一个半小时才打完。
  • 原因是我将被修改成黑点的点的父链又单独考虑了一遍,需要树链剖分+树状数组。
  • 所以代码会很长……
#include<cstdio>
#define L tr[k].lc
#define R tr[k].rc
using namespace std;
int const N=1e5+5,M=2e5+5;
inline int read(){
    int ss(0);char bb(getchar());
    while(bb<48||bb>57)bb=getchar();
    while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar();
    return ss;
}
int n,m;
int head[N],Next[M],to[M],t;
int val[N];
bool vis[N];
int l[N],r[N],tot;
int siz[N],son[N],fa[N],dep[N],top[N];
int blk;
struct node{
    int lc,rc,w,f;
}tr[N<<2];
int BIT[N];
inline void add(int x,int y){
    to[++t]=y;
    Next[t]=head[x],head[x]=t;
    return ;
}
int dfs1(int x,int y){
    for(int i=head[x],nw=0,dnow=dep[x]+1,z;i;i=Next[i])
        if((z=to[i])^y){
            dep[z]=dnow,fa[z]=x;
            siz[x]+=dfs1(z,x);
            if(siz[z]>nw)nw=siz[z],son[x]=z;
        }
    return ++siz[x];
}
void dfs2(int x,int y){
    l[x]=++tot,top[x]=y;
    if(!son[x]){r[x]=tot;return ;}
    dfs2(son[x],y);
    for(int i=head[x],sw=son[x],fw=fa[x];i;i=Next[i])
        if(to[i]!=sw && to[i]!=fw)dfs2(to[i],to[i]);
    r[x]=tot;
    return ;
}
void build(int x,int y,int k){
    L=x,R=y;
    if(x==y)return ;
    int mid=x+y>>1;
    return build(x,mid,k<<1),build(mid+1,y,k<<1|1);
}
inline int max(int x,int y){
    return x>y?x:y;
}
inline void down(int k){
    int lk=k<<1,rk=lk|1,z=tr[k].f;
    tr[k].f=0;
    tr[lk].w=max(z,tr[lk].w),tr[lk].f=max(z,tr[lk].f);
    tr[rk].w=max(z,tr[rk].w),tr[rk].f=max(z,tr[rk].f);
    return ;
}
inline int ask(int x,int k){
    while(L^R){
        if(tr[k].f)down(k);
        if(x<=(L+R>>1))k<<=1;
        else k=k<<1|1;
    }
    return tr[k].w;
}
void getmax(int x,int y,int z,int k){
    tr[k].w=max(z,tr[k].w);
    if(L>=x&&R<=y){tr[k].f=max(z,tr[k].f);return ;}
    int mid=L+R>>1;
    if(x<=mid)getmax(x,y,z,k<<1);
    if(y>mid)getmax(x,y,z,k<<1|1);
    return ;
}
inline void change(int x,int y){
    while(x<=n)BIT[x]+=y,x+=x&-x;
    return ;
}
inline int query(int x){
    int ans=0;
    while(x)ans+=BIT[x],x-=x&-x;
    return ans;
}
inline void update(int x){
    int fx=fa[top[x]];
    while(fx)change(l[top[x]],1),change(l[x]+1,-1),x=fx,fx=fa[top[x]];
    return change(1,1),change(l[x]+1,-1);
}
inline void modify(int x){
    while(!vis[x]){
        if(l[fa[x]]<l[x])getmax(l[fa[x]],l[x]-1,val[fa[x]],1);
        if(r[fa[x]]>r[x])getmax(r[x]+1,r[fa[x]],val[fa[x]],1);
        vis[x]=1,x=fa[x];
    }
    return ;
}
int main(){
    //freopen("lca2.in","r",stdin);
    //freopen("1.out","w",stdout);
    n=read(),m=read();
    for(register int i=1;i<=n;++i)val[i]=read();
    for(register int i=1,ff,tt;i<n;++i)
        ff=read(),tt=read(),add(ff,tt),add(tt,ff);
    dfs1(1,0),dfs2(1,1);
    build(1,n,1),vis[1]=1;
    while(m--){
        char bb=getchar();
        while(bb^'Q'&&bb^'M')bb=getchar();
        int x=read();
        if(bb=='Q'){
            if(blk)printf("%d\n",query(l[x])?max(val[x],ask(l[x],1)):ask(l[x],1));
            else puts("-1");
            continue;
        }
        update(x),blk=1;
        getmax(l[x],r[x],val[x],1);
        modify(x);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/remarkable/p/11713763.html