[CLYZ2017]day2


冒泡排序

Solution

30分

直接模拟.

70分

求出\(a\)中每个数之前比它大的数的个数,取\(max\).

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 1000005
using namespace std;
typedef long long ll;
int a[N],pre[N],n,s,b,c,d,cnt,ans;
inline int read(){
    int ret=0;char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c)){
        ret=(ret<<1)+(ret<<3)+c-'0';
        c=getchar();
    }
    return ret;
}
inline bool chk(){
    for(int i=1;i<=n;++i)
        if(a[i]!=i)
            return false;
    return true; 
}
inline int lowbit(int x){
    return x&(-x);
}
inline int ask(int k){
    int ret=0;
    for(int i=k;i;i-=lowbit(i))
        ret+=pre[i];
    return ret;
}
inline void add(int k){
    for(int i=k;i<=n;i+=lowbit(i))
        ++pre[i];
}
inline void Aireen(){
    scanf("%d%d%d%d%d",&n,&s,&b,&c,&d);
    for(int i=1,j,t;i<=n;++i){
        a[i]=i;
        s=(1ll*s*b+c)%d;
        swap(a[i],a[s%i+1]);
    }
    if(n<=1000){
        int t;cnt=0;
        while(!chk()){
            ++cnt;
            for(int i=1;ia[i+1]){
                    t=a[i];a[i]=a[i+1];a[i+1]=t;
                }
        }
        printf("%d\n",cnt);
        return;
    }
    for(int i=1;i<=n;++i){
        ans=max(ans,ask(n)-ask(a[i]));
        add(a[i]);
    }
    printf("%d\n",ans);
}
int main(){
    freopen("bubble.in","r",stdin);
    freopen("bubble.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}

100分

\(ans=max\{i-a_i\}\).

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 30000005
using namespace std;
typedef long long ll;
int a[N],n,s,b,c,d,ans;
inline void Aireen(){
    scanf("%d%d%d%d%d",&n,&s,&b,&c,&d);
    for(register int i=1,j,t;i<=n;++i){
        a[i]=i;
        s=(1ll*s*b+c)%d;
        swap(a[i],a[s%i+1]);
    }
    for(register int i=1;i<=n;++i)
        ans=max(ans,i-a[i]);
    printf("%d\n",ans);
}
int main(){
    freopen("bubble.in","r",stdin);
    freopen("bubble.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}

代码问题

有些下标计算爆int.

字符串匹配

Solution

10分

暴力求解.

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 1000005
using namespace std;
typedef long long ll;
int s[N],t[N],g[N],nxt[N],tot[N],ans[N],n,m,k,c,q,cnt,sum;
bool b[N];
inline int read(){
    int ret=0;char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c)){
        ret=(ret<<1)+(ret<<3)+c-'0';
        c=getchar();
    }
    return ret;
}
inline bool chk(int u){
    for(int i=1;i<=c;++i) 
        for(int j=g[i],k=s[u+g[i]];j;j=nxt[j]){
            if(s[u+j]!=k) return false;
        } 
    return true;
}
inline void Aireen(){
    q=read();c=read();
    while(q--){
        n=read();m=read();
        for(int i=1;i<=n;++i)
            s[i]=read();
        for(int i=1;i<=m;++i)
            t[i]=read();
        memset(g,0,sizeof(g));
        memset(b,0,sizeof(b));
        memset(tot,0,sizeof(tot));
        if(n

100分

对字符串相同字符间的相邻距离进行\(kmp\).
会出现上一个相同字符不出现在目前匹配的子串中,在跳nxt的判断中,分类讨论即可.

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 1000005
using namespace std;
int s[N],t[N],nxt[N],lst[N],ans[N],n,m,c,q,cnt;
inline int read(){
    int ret=0;char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c)){
        ret=(ret<<1)+(ret<<3)+c-'0';
        c=getchar();
    }
    return ret;
}
inline bool chk1(int i,int j){
    if(j

阅读

Solution

20分

\(f[i]=max\{f[j]-\lceil\frac{t[i]-t[j]}{D}\rceil\times{A}\}+b[i]\).

50分

对于\(D\leq100\),对于每个\(t_i\;mod\;D\)同余的贪心.枚举\(mod\;D\)不同的值即可.

100分

可以发现,
\(t[j]时,\(\lceil\frac{t[i]-t[j]}{D}\rceil=\lfloor\frac{t[i]}{D}\rfloor-\lfloor\frac{t[j]}{D}\rfloor+1\);
\(t[j]\geq{t[i]}\)时,\(\lceil\frac{t[i]-t[j]}{D}\rceil=\lfloor\frac{t[i]}{D}\rfloor-\lfloor\frac{t[j]}{D}\rfloor\);
\(f[i]-\lfloor\frac{m}{D}\rfloor-\lfloor\frac{k}{D}\rfloor=max\{max\{f[1...j-1]\}-a,max\{f[j...m]\}\}\)
(\(j\)表示\(mod\;D\)的值离散后的位置,离散后共有m个值).
最后全部加上\(\lfloor\frac{m}{D}\rfloor-\lfloor\frac{k}{D}\rfloor\)就好啦.
P.S.写代码的时候比较傻,所以写得正确性和简洁性堪忧.

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define N 100005
#define M 300005
using namespace std;
typedef long long ll;
ll f[N],g[N],b[N],t[N],a,d,m,k,ans;
int p[N],idp[N],ids[N],n,cnt;
inline int read(){
    int ret=0;char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c)){
        ret=(ret<<1)+(ret<<3)+c-'0';
        c=getchar();
    }
    return ret;
}
//i比j优 
inline bool cmp(int i,int j){
    return f[i]+t[i]/d*a>f[j]+t[j]/d*a;
}
inline int lowbit(int k){
    return k&(-k);
}
inline void change(int k){
    for(int i=k;i<=cnt;i+=lowbit(i))
        if(!idp[i]||cmp(g[k],idp[i])) idp[i]=g[k]; 
    for(int i=cnt-k+1;i<=cnt;i+=lowbit(i)){
        if(!ids[i]||cmp(g[k],ids[i])) ids[i]=g[k];
    }
}
inline int pre(int k){
    int ret=0;
    for(int i=k;i;i-=lowbit(i))
        if(!ret) ret=idp[i];
        else if(cmp(idp[i],ret))
            ret=idp[i];
    return ret;
}
inline int suf(int k){
    int ret=0;
    for(int i=cnt-k+1;i;i-=lowbit(i))
        if(!ret) ret=ids[i];
        else if(cmp(ids[i],ret))
            ret=ids[i];
    return ret;
}
inline void Aireen(){
    scanf("%lld%lld%lld%lld%d",&k,&m,&d,&a,&n);
    for(int i=1;i<=n;++i)
        scanf("%lld%lld",&t[i],&b[i]);
    if(n<=1000){
        for(int i=1;i<=n;++i){
            if((t[i]-k)%d) f[i]=-((t[i]-k)/d+1ll)*a+b[i];
            else f[i]=-(t[i]-k)/d*a+b[i];
            for(int j=1;j=0;--k)
                if((t[i]-t[j=g[k]])%d)
                    f[i]=max(f[i],f[j]-((t[i]-t[j])/d+1ll)*a+b[i]);
                else f[i]=max(f[i],f[j]-(t[i]-t[j])/d*a+b[i]);
            if(!g[t[i]%d]) g[t[i]%d]=i;
            else if(cmp(i,g[t[i]%d]))
                g[t[i]%d]=i;
        }
        if((m-k)%d) ans=-((m-k)/d+1ll)*a;
        else ans=-(m-k)/d*a;
        for(int i=1;i<=n;++i)
            if((m-t[i])%d)
                ans=max(ans,f[i]-((m-t[i])/d+1ll)*a);
            else ans=max(ans,f[i]-(m-t[i])/d*a);
        printf("%lld\n",ans);
        return; 
    }
    for(int i=1;i<=n;++i)
        p[i]=(int)(t[i]%d);
    sort(p+1,p+1+n);cnt=1;
    for(int i=2;i<=n;++i)
        if(p[i]!=p[i-1]) p[++cnt]=p[i];
    for(int i=1,j,l;i<=n;++i){
        if((t[i]-k)%d) f[i]=-((t[i]-k)/d+1ll)*a+b[i];
        else f[i]=-(t[i]-k)/d*a+b[i];
        l=lower_bound(p+1,p+1+cnt,(int)(t[i]%d))-p;
        if(l-1){
            j=pre(l-1);
            if(j){
                if((t[i]-t[j])%d) 
                    f[i]=max(f[i],f[j]-((t[i]-t[j])/d+1ll)*a+b[i]);
                else f[i]=max(f[i],f[j]-(t[i]-t[j])/d*a+b[i]);
            }
        }
        j=suf(l);
        if(j){
            if((t[i]-t[j])%d) 
                f[i]=max(f[i],f[j]-((t[i]-t[j])/d+1ll)*a+b[i]);
            else f[i]=max(f[i],f[j]-(t[i]-t[j])/d*a+b[i]);
        }
        if(!g[l]){
            g[l]=i;change(l);
        }
        else if(cmp(i,g[l])){
            g[l]=i;change(l);
        }
    }
    if((m-k)%d) ans=-((m-k)/d+1ll)*a;
    else ans=-(m-k)/d*a;
    for(int i=1;i<=n;++i)
        if((m-t[i])%d)
            ans=max(ans,f[i]-((m-t[i])/d+1ll)*a);
        else ans=max(ans,f[i]-(m-t[i])/d*a);
    printf("%lld\n",ans);
}
int main(){
    freopen("reading.in","r",stdin);
    freopen("reading.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}