Submission #50973

#TimeUsernameProblemLanguageResultExecution timeMemory
50973model_code영역 (JOI16_ho_t4)C++17
100 / 100
125 ms7052 KiB
#include <cstdio> #include <cstdlib> int N,K,dx,dy; char moves[100008]; typedef struct { long long vx; long long vy; long long minv; long long maxv; }list_structure; list_structure lists_temp[100008]; int lists_temp_len=0; list_structure lists[100008]; int lists_len=1; void list_add(list_structure *ls,long long sx,long long sy,long long mnv,long long mxv) { ls->vx=sx; ls->vy=sy; ls->minv=mnv; ls->maxv=mxv; } void add_point(long long sx,long long sy,long long mnv,long long mxv) { //mod dx で正しい場所を算出し,その場所に点を追加. if(dx==0) { list_add(&lists_temp[lists_temp_len],sx,sy,mnv,mxv); lists_temp_len++; } else { if(sx>=dx) { long long temp=sx/dx; add_point(sx-temp*dx,sy-temp*dy,mnv+temp,mxv+temp); return; } if(sx<0) { long long temp=-sx/dx+1; add_point(sx+temp*dx,sy+temp*dy,mnv-temp,mxv-temp); return; } list_add(&lists_temp[lists_temp_len],sx,sy,mnv,mxv); lists_temp_len++; } } int comp(const void *ka,const void *kb) { list_structure *a = (list_structure *)ka; list_structure *b = (list_structure *)kb; if(a->vx != b->vx) { if(a->vx < b->vx) return -1; return 1; } if(a->vy != b->vy) { if(a->vy < b->vy) return -1; return 1; } if(a->minv != b->minv) { if(a->minv < b->minv) return -1; return 1; } if(a->maxv < b->maxv) return -1; if(a->maxv > b->maxv) return 1; return 0; } int comp_xy(const void *ka,const void *kb) { list_structure *a = (list_structure *)ka; list_structure *b = (list_structure *)kb; if(a->vx != b->vx) { if(a->vx < b->vx) return -1; return 1; } if(a->vy != b->vy) { if(a->vy < b->vy) return -1; return 1; } return 0; } int findl(long long sx,long long sy) { //(sx,sy) に相当する区間がリストにあればその場所を、ないなら -1 を返す. //複数あるならそれらの一番左の場所を返す. int minr=0; int maxr=lists_len-1; list_structure temp; temp.vx=sx; temp.vy=sy; while(minr<maxr) { int hf=(minr+maxr)/2; if(comp_xy(&lists[hf],&temp)<0) { minr=hf+1; } else { maxr=hf; } } if(lists[minr].vx!=sx||lists[minr].vy!=sy) return -1; return minr; } int findr(long long sx,long long sy) { //(sx,sy) に相当する区間がリストにあればその場所を返す. //複数あるならそれらの一番右の場所を返す. int minr=0; int maxr=lists_len-1; list_structure temp; temp.vx=sx; temp.vy=sy; while(minr<maxr) { int hf=(minr+maxr+1)/2; if(comp_xy(&lists[hf],&temp)>0) { maxr=hf-1; } else { minr=hf; } } return minr; } int exist(long long vx,long long vy) { //(vx,vy) に相当する場所に 1 つ以上区間があるか判定. if(dx==0) { if(findl(vx,vy)<0) return 0; return 1; } if(vx<0) { long long temp=-vx/dx+1; return exist(vx+temp*dx,vy+temp*dy); } if(vx>=dx) { long long temp=vx/dx; return exist(vx-temp*dx,vy-temp*dy); } if(findl(vx,vy)<0) return 0; return 1; } void calcplace(long long vx,long long vy,int *retl,int *retr,long long *retoffset) { //(vx,vy) に相当する区間を表す集合 (retl から retr の範囲として返す) を求める. //retoffset には、共通部分を取るときに必要な移動を保存. *retoffset=0; if(dx) { if(vx<0) { *retoffset=-vx/dx+1; *retoffset=-(*retoffset); } if(vx>=dx) { *retoffset=vx/dx; } } *retl=findl(vx-(*retoffset)*dx,vy-(*retoffset)*dy); *retr=findr(vx-(*retoffset)*dx,vy-(*retoffset)*dy); } int range_minv_a[100008]; int range_maxv_a[100008]; int range_minv_b[100008]; int range_maxv_b[100008]; int range_minv_temp[100008]; int range_maxv_temp[100008]; int range_a_len,range_b_len; void range_cpya(int fl,int fr,long long offset) { //range_*_a に区間列をコピー range_a_len=0; for(int i=fl;i<=fr;i++) { range_minv_a[range_a_len]=lists[i].minv-offset; range_maxv_a[range_a_len]=lists[i].maxv-offset; range_a_len++; } } void range_cpyb(int fl,int fr,long long offset) { //range_*_b に区間列をコピー range_b_len=0; for(int i=fl;i<=fr;i++) { range_minv_b[range_b_len]=lists[i].minv-offset; range_maxv_b[range_b_len]=lists[i].maxv-offset; range_b_len++; } } void merge(void) { //2 つの区間列 range_*_a と range_*_b の共通部分となる区間列を計算し、range_*_a に保存. int range_temp_len=0; int ia=0; int ib=0; while(ia<range_a_len&&ib<range_b_len) { if(range_minv_a[ia]<range_minv_b[ib]) { range_minv_a[ia]=range_minv_b[ib]; if(range_minv_a[ia]>range_maxv_a[ia]) ia++; } else if(range_minv_a[ia]>range_minv_b[ib]) { range_minv_b[ib]=range_minv_a[ia]; if(range_minv_b[ib]>range_maxv_b[ib]) ib++; } else { range_minv_temp[range_temp_len]=range_minv_a[ia]; if(range_maxv_a[ia]>range_maxv_b[ib]) { range_maxv_temp[range_temp_len]=range_maxv_b[ib]; ib++; } else { range_maxv_temp[range_temp_len]=range_maxv_a[ia]; ia++; } range_temp_len++; } } for(int i=0;i<range_temp_len;i++) { range_minv_a[i]=range_minv_temp[i]; range_maxv_a[i]=range_maxv_temp[i]; } range_a_len=range_temp_len; } int main() { scanf("%d%d",&N,&K); scanf("%s",moves); for(int i=0;i<N;i++) { if(moves[i]=='E') dx++; if(moves[i]=='N') dy++; if(moves[i]=='W') dx--; if(moves[i]=='S') dy--; } if(dx<0) { dx=-dx; for(int i=0;i<N;i++) { if(moves[i]=='E') { moves[i]='W'; } else if(moves[i]=='W') { moves[i]='E'; } } } if(dy<0) { dy=-dy; for(int i=0;i<N;i++) { if(moves[i]=='N') { moves[i]='S'; } else if(moves[i]=='S') { moves[i]='N'; } } } //入力を dx>0 となるように回転,反転させる (dx=dy=0 のとき以外). if(dx==0&&dy>0) { int temp=dy; dy=dx; dx=temp; for(int i=0;i<N;i++) { if(moves[i]=='E') { moves[i]='N'; } else if(moves[i]=='N') { moves[i]='E'; } if(moves[i]=='S') { moves[i]='W'; } else if(moves[i]=='W') { moves[i]='S'; } } } //dx=dy=0 のとき,K=1 としておく. if(dx==0) K=1; add_point(0,0,0,K-1); int nx=0; int ny=0; for(int i=0;i<N;i++) { if(moves[i]=='E') nx++; if(moves[i]=='N') ny++; if(moves[i]=='W') nx--; if(moves[i]=='S') ny--; add_point(nx,ny,0,K-1); } //算出した各区間の重なったもの同士を結合. qsort(lists_temp,lists_temp_len,sizeof(list_structure),comp); list_add(&lists[0],lists_temp[0].vx,lists_temp[0].vy,lists_temp[0].minv,lists_temp[0].maxv); for(int i=1;i<lists_temp_len;i++) { if(lists[lists_len-1].vx!=lists_temp[i].vx||lists[lists_len-1].vy!=lists_temp[i].vy) { list_add(&lists[lists_len],lists_temp[i].vx,lists_temp[i].vy,lists_temp[i].minv,lists_temp[i].maxv); lists_len++; } else { if(lists[lists_len-1].maxv+1<lists_temp[i].minv) { list_add(&lists[lists_len],lists_temp[i].vx,lists_temp[i].vy,lists_temp[i].minv,lists_temp[i].maxv); lists_len++; } else { if(lists[lists_len-1].maxv<lists_temp[i].maxv) lists[lists_len-1].maxv=lists_temp[i].maxv; } } } long long sol=0; //正方形の左下を固定した場合の個数を計算. for(int i=0;i<lists_len;i++) { if(i) if(lists[i].vx==lists[i-1].vx&&lists[i].vy==lists[i-1].vy) continue; //既に調べているなら除外. int bx=lists[i].vx; int by=lists[i].vy; if(exist(bx+1,by)+exist(bx,by+1)+exist(bx+1,by+1)==3) { int fl,fr; long long offset; calcplace(bx,by,&fl,&fr,&offset); range_cpya(fl,fr,offset); calcplace(bx+1,by,&fl,&fr,&offset); range_cpyb(fl,fr,offset); merge(); calcplace(bx,by+1,&fl,&fr,&offset); range_cpyb(fl,fr,offset); merge(); calcplace(bx+1,by+1,&fl,&fr,&offset); range_cpyb(fl,fr,offset); merge(); for(int i=0;i<range_a_len;i++) sol+=range_maxv_a[i]-range_minv_a[i]+1; } } printf("%lld\n",sol); return 0; }

Compilation message (stderr)

2016_ho_t4.cpp: In function 'int main()':
2016_ho_t4.cpp:193:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d",&N,&K);
  ~~~~~^~~~~~~~~~~~~~
2016_ho_t4.cpp:194:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%s",moves);
  ~~~~~^~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...