1. 程式人生 > >BZOJ5103 : [POI2018]Róznorodno

BZOJ5103 : [POI2018]Róznorodno

一段 %d unsigned 區間 typedef class 枚舉 處理 每次

從上到下枚舉上下底邊,那麽涉及兩行的添加和刪除。

首先預處理出對於每一列,每個位置添加和刪除時,是否會對往下$k$個裏出現這個顏色造成影響。

然後對於每種顏色維護一個長度為$m$的bitset,表示哪些列出現過該顏色。

那麽每次修改時,找到前驅和後繼,對這一行答案的影響是一段區間加,差分前綴和即可。

時間復雜度$O(\frac{nm^2}{64})$。

#include<cstdio>
typedef unsigned int U;
const int N=3010,M=100010,BUF=72000000;
char Buf[BUF],*buf=Buf;
int n,m,K,lim,i,j,k,u,d,a[N][N],cnt[M],s[N],mx;long long ans;bool in[N][N],ou[N][N];
U f[M][N/32+5];
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
inline void add(U*f,int x){
  int y=x>>5,pre=-1,suf=-1;
  if(f[y]){
    int o=x&31;U z=f[y];
    for(int i=o-1;~i;i--)if(z>>i&1){pre=y<<5|i;break;}
    for(int i=o+1;i<32;i++)if(z>>i&1){suf=y<<5|i;break;}
  }
  if(pre<0)for(int i=y-1;~i;i--)if(f[i]){pre=i<<5|(31-__builtin_clz(f[i]));break;}
  if(suf<0)for(int i=y+1;i<=lim;i++)if(f[i]){suf=i<<5|__builtin_ctz(f[i]);break;}
  int l=max(pre+1,x-K+1),r=min(x,suf-K);
  if(l<=r)s[l]++,s[r+1]--;
  f[y]^=1U<<(x&31);
}
inline void del(U*f,int x){
  int y=x>>5,pre=-1,suf=-1;
  f[y]^=1U<<(x&31);
  if(f[y]){
    int o=x&31;U z=f[y];
    for(int i=o-1;~i;i--)if(z>>i&1){pre=y<<5|i;break;}
    for(int i=o+1;i<32;i++)if(z>>i&1){suf=y<<5|i;break;}
  }
  if(pre<0)for(int i=y-1;~i;i--)if(f[i]){pre=i<<5|(31-__builtin_clz(f[i]));break;}
  if(suf<0)for(int i=y+1;i<=lim;i++)if(f[i]){suf=i<<5|__builtin_ctz(f[i]);break;}
  int l=max(pre+1,x-K+1),r=min(x,suf-K);
  if(l<=r)s[l]--,s[r+1]++;
}
int main(){
  fread(Buf,1,BUF,stdin);read(n),read(m),read(K);
  for(i=1;i<=n;i++)for(j=1;j<=m;j++)read(a[i][j]);
  for(j=1;j<=m;j++){
    for(d=1;d<K;d++)if(!(cnt[a[d][j]]++))in[d][j]=1;
    for(u=0;d<=n;u++,d++){
      if(u)if(!(--cnt[a[u][j]]))ou[u][j]=1;
      if(!(cnt[a[d][j]]++))in[d][j]=1;
    }
    for(i=1;i<=n;i++)cnt[a[i][j]]=0;
  }
  lim=(m+1)>>5;
  for(i=1;i<M;i++){
    f[i][0]=1;
    f[i][(m+1)>>5]|=1U<<((m+1)&31);
  }
  for(d=1;d<K;d++)for(j=1;j<=m;j++)if(in[d][j])add(f[a[d][j]],j);
  for(u=0;d<=n;u++,d++){
    if(u)for(j=1;j<=m;j++)if(ou[u][j])del(f[a[u][j]],j);
    for(j=1;j<=m;j++)if(in[d][j])add(f[a[d][j]],j);
    for(j=1,k=0;j+K-1<=m;j++){
      k+=s[j];
      if(k>mx)mx=k;
      ans+=k;
    }
  }
  return printf("%d %lld",mx,ans),0;
}

  

BZOJ5103 : [POI2018]Róznorodno