题解 P5102 【[JOI 2016 Final]领地】

· · 题解

路径上经过的所有点可以用按照轮次和位置表示为(x,y,r)表示第r轮走在(x,y)位置

如果我们默认每次的起点都是(0,0)那么(x,y,r)表示的就是(x+r\times tx,y+r\times ty)

我们如果把所有的点的x坐标都限制在0tx范围内,那么我们就把所有本质一样的点都压在了一个位置,只要轮数一致,那就是完全重合的两个点

对于x不在0tx之间的点,我们通过调整轮数使它在合法区间内

我们对于每个点可以处理出存在的轮数区间,考虑每个店作为左下角时,其它三个点对应的位置和轮数区间,四个点所对应的轮数同时合法那就计入答案,也就是将区间统一标准后求交集即可

具体细节可以看代码 ```cpp #include<cstdio> #include<iostream> #include<queue> #include<algorithm> #include<cstring> #include<set> #include<vector> #include<cmath> #include<map> #define PII pair<int,int> #define pb push_back #define ep emplace_back #define mp make_pair #define fi first #define se second using namespace std; inline int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();} return f==1?x:~x+1; } inline void print(int x){ if(x<0) putchar('-'),x=~x+1; if(x>=10) print(x/10); putchar((x%10)|48); } int n,k; char str[100010]; map<PII,vector<PII> >Map; int tx,ty; void merge(vector<PII>&s,vector<PII>t){ vector<PII>res; auto it=t.begin(); for(auto i:s){ while(it!=t.end()){ while(it!=t.end()&&it->se<i.fi) ++it; if(it==t.end()) break ; if(it->fi>i.se) break ; res.ep(max(it->fi,i.fi),min(it->se,i.se)); if(it->se>i.se) break ; ++it; } } s=res; } int main(){ n=read(),k=read(); scanf("%s",str+1); for(int i=1;i<=n;++i){ switch(str[i]){ case 'E':++tx;break ; case 'N':++ty;break ; case 'W':--tx;break ; case 'S':--ty;break ; } } if(tx==0&&ty==0) {k=1;tx=1e9;} else if(tx==0){ swap(tx,ty); for(int i=1;i<=n;++i){ switch(str[i]){ case 'E':str[i]='N';break; case 'N':str[i]='E';break; case 'W':str[i]='S';break; case 'S':str[i]='W';break; } } } if(tx<0){ for(int i=1;i<=n;++i){ switch(str[i]){ case 'E':str[i]='W';break; case 'W':str[i]='E';break; } } tx=-tx; } if(ty<0){ for(int i=1;i<=n;++i){ switch(str[i]){ case 'N':str[i]='S';break; case 'S':str[i]='N';break; } } ty=-ty; } Map[mp(0,0)].pb(mp(1,k)); for(int i=1;i<=n;++i){ static int x=0,y=0; switch(str[i]){ case 'E':++x;break ; case 'N':++y;break ; case 'W':--x;break ; case 'S':--y;break ; } // printf("i:%d,x:%d,y:%d\n",i,x,y); int d=x/tx; int ax=x-d*tx,ay=y-d*ty; if(ax<0) --d,ax+=tx,ay+=ty; // printf("d:%d,ax:%d,ay:%d\n\n\n",d,ax,ay); Map[mp(ax,ay)].pb(mp(d+1,d+k)); } for(auto &i:Map){ auto &v=i.se; sort(v.begin(),v.end()); int l=-1e6,r=-1e6; vector<PII>nw; for(auto p:v){ if(l==-1e6){ l=p.fi,r=p.se; } else if(p.fi<=r) r=max(r,p.se); else{ nw.ep(l,r); l=p.fi,r=p.se; } } nw.ep(l,r); v=nw; } auto mt=[&](PII x){ if(x.fi>=tx) x.fi-=tx,x.se-=ty; return x; }; long long ans=0; for(auto i:Map){ PII nod=i.fi; PII x2=mp(nod.fi+1,nod.se),x3=mp(nod.fi,nod.se+1),x4=mp(nod.fi+1,nod.se+1); if(Map.count(mt(x2))&&Map.count(mt(x3))&&Map.count(mt(x4))){ auto gs=[&](PII x){ if(x.fi>=tx){ x.fi-=tx,x.se-=ty; vector<PII>t=Map[x]; vector<PII>res(t.size()); auto minus=[&](PII a){ return mp(a.fi-1,a.se-1); }; // printf("Mns:\n"); // for(auto a:t) printf("%d %d\n",a.fi,a.se); std::transform(t.begin(),t.end(),res.begin(),minus); // printf("Res:\n"); // for(auto a:res) printf("%d %d\n",a.fi,a.se); // printf("\n\n"); return res; } else return Map[x]; }; vector<PII>v=i.se; merge(v,gs(x2));merge(v,gs(x3));merge(v,gs(x4)); for(auto x:v) ans+=x.se-x.fi+1; // printf("%d %d ans:%d\n",nod.fi,nod.se,ans); } } printf("%lld\n",ans); return 0; } ```