NOIP2014提高組模擬8.9
阿新 • • 發佈:2019-02-07
#include #include struct ecc{ int se,fi,ln,la; }b[1110*1100]; int a[1101][1101],n,m,i,j,k,g[1210*1200],tot;//g為連結串列頭指標,b.se為次小值,b.fi為最小值,b.ln行號,b.la為上一次的更新的地址 bool p; int main(){ scanf("%d%d",&n,&m); k=0; b[0].se=m+1;b[0].fi=m+1; for(i=1;i<=n;i++){ for(j=1;j<=m;j++){ scanf("%d",&a[i][j]);p=0; if(i!=b[g[a[i][j]]].ln)++tot,k=tot,p=1;else k=g[a[i][j]]; if(j<=b[g[a[i][j]]].fi){ //更新最小次小值 b[k].se=b[g[a[i][j]]].fi; b[k].fi=j; if(p)b[k].la=g[a[i][j]],g[a[i][j]]=k; b[k].ln=i; }else if(j<=b[g[a[i][j]]].se){ b[k].se=j; b[k].fi=b[g[a[i][j]]].fi; if(p)b[k].la=g[a[i][j]],g[a[i][j]]=k; b[k].ln=i; } } } long long ans(0);int la; for(i=1;i<=n*m;i++){ //統計次數 k=g[i];la=g[i]; ans+=(n-b[la].ln+1)*(b[la].se-b[la].fi);//對於最後一次更新,b.ln~n行的最小次小區間的點為矩陣右下角的點的矩陣都是可行解 ans%=19900907; if(!k)continue; while(k){ if(k!=g[i])ans+=(b[la].ln-b[k].ln)*(b[k].se-b[k].fi),ans%=19900907;//計算每次更新間的答案 la=k; k=b[k].la; } } printf("%lld",ans); }