ICPC2023合肥站:D. Balanced Array

这道题我也没有想到正解,用了一个奇技淫巧过了。

显然,对于每个k,它所满足要求的i肯定是一个区间。

我们不难发现,满足条件的 k k k基本都很大(相对于(n-1)/2),因此我们维护最大的20个满足条件的k即可。

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define dwn(i,x,y) for(int i=x;i>=y;i--)
#define ll long long
using namespace std;
template<typename T>inline void qr(T &x){
    x=0;int f=0;char s=getchar();
    while(!isdigit(s))f|=s=='-',s=getchar();
    while(isdigit(s))x=x*10+s-48,s=getchar();
    x=f?-x:x;
}
int cc=0,buf[31];
template<typename T>inline void qw(T x){
    if(x<0)putchar('-'),x=-x;
    do{buf[++cc]=int(x%10);x/=10;}while(x);
    while(cc)putchar(buf[cc--]+'0');
}
const int N=2e6+10;
int n,a[N];char s[30];
int tp,sta[30];
bool check(int i,int j){
    return 2*a[i-j]==a[i]+a[i-2*j];
}
void push(int x){
    if(tp==20){
        rep(i,1,tp-1)sta[i]=sta[i+1];
        sta[tp]=x;
    }
    else{
        sta[++tp]=x;
    }
}
void update(int now){
    rep(i,1,tp)if(!check(now,sta[i]))sta[i]=0;
    int last=tp;tp=0;
    rep(i,1,last){
        if(sta[i])sta[++tp]=sta[i];
    }
}
void solve(){
    qr(n);
    rep(i,1,n){
        scanf("%s",s+1);int len=strlen(s+1);
        rep(j,1,len){
            int w;
            if('0'<=s[j]&&s[j]<='9')w=s[j]-'0';
            else if('a'<=s[j]&&s[j]<='z')w=s[j]-'a'+10;
            else w=s[j]-'A'+36;
            a[i]=a[i]*62+w;
        }
    }
    rep(i,1,n){
        if(i>=3&&i%2==1){
            int num=i/2;
            if(check(i,num))push(num);
        }
        update(i);
        putchar(tp?'1':'0');
    }
}
int main(){
    int tt;tt=1;
    while(tt--)solve();
    return 0;
}

后面看到题解居然能够用哈希进行快速的判断。
考虑一段数,我们把它复制成三份,第一份不变,第二份往左边移动k个位置,第三份往右边移动k个位置,那很明显就是上下的和等于中间的两倍。

#include<bits/stdc++.h>
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define dwn(i,x,y) for(int i=x;i>=y;i--)
#define ll long long
#define ull unsigned long long
using namespace std;
template<typename T>inline void qr(T &x){
    x=0;int f=0;char s=getchar();
    while(!isdigit(s))f|=s=='-',s=getchar();
    while(isdigit(s))x=x*10+s-48,s=getchar();
    x=f?-x:x;
}
int cc=0,buf[31];
template<typename T>inline void qw(T x){
    if(x<0)putchar('-'),x=-x;
    do{buf[++cc]=int(x%10);x/=10;}while(x);
    while(cc)putchar(buf[cc--]+'0');
}
const int N=2e6+10;
int n,a[N],c[N];
ull hsh[N],val[N];
ull hsh2[N],val2[N];
ull calc(int l,int r){
    if(l>r)return 0;
    return hsh[r]-hsh[l-1]*val[r-l+1];
}
ull calc2(int l,int r){
    if(l>r)return 0;
    return hsh2[r]-hsh2[l-1]*val2[r-l+1];
}
bool check(int i,int k){
    return calc(1,i-2*k)+calc(2*k+1,i)==calc(k+1,i-k)*2ull
    &&calc2(1,i-2*k)+calc2(2*k+1,i)==calc2(k+1,i-k)*2ull;
}
void solve(){
    qr(n);
    if(n<=2){
        rep(i,1,n)putchar('0');
        return;
    }
    char s[20];
    val[0]=1;
    val2[0]=1;
    rep(i,1,n){
        scanf("%s",s+1);
        int len=strlen(s+1);
        rep(j,1,len){
            if('0'<=s[j]&&s[j]<='9')a[i]=a[i]*62+(s[j]-'0');
            else if('a'<=s[j]&&s[j]<='z')a[i]=a[i]*62+(s[j]-'a'+10);
            else a[i]=a[i]*62+(s[j]-'A'+36);
        }
        val[i]=val[i-1]*998244353;
        hsh[i]=hsh[i-1]*998244353+a[i];
        val2[i]=val2[i-1]*200000009;
        hsh2[i]=hsh2[i-1]*200000009+a[i];
    }
    int now=1;
    putchar('0');putchar('0');
    rep(i,3,n){
        while(now+1<=(i-1)/2&&!check(i,now))now++;
        if(check(i,now))putchar('1');
        else putchar('0');
    }
}
int main(){
    int tt;tt=1;
    while(tt--)solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值