题解:P5102 [JOI 2016 Final] 领地 / Territory
分析
首先
然后将一次走的
注意到每次偏移的是固定量,自然地想到取模。一开始每个点的位置可以用二元组
有了这些后,我们尝试一步步地做这题。
首先,对于第一个整体中每一个点
下一步我们考虑计算答案。我们会发现共有
有点乱,具体细节看代码。
有几个重要操作提一下:
①:区间取并的核心思想是:通过 set 二分出左右两端与新加入区间相交的地方。插入一个区间时间为
②:两个集合中的区间取交可以先转化为 vector 类型,然后在一个集合中固定区间,通过双指针在另一个集合中寻找与固定的区间有交的区间。
分析一下时间复杂度,动态区间取并是
还有一点没解决,就是
贴个代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
const int N=1e5,INF=1e15;
int T,n,k;
int dx,dy;
char a[N+5];
map<pii,set<pii>> mp;
void addv(int &x,int &y,char ch){
if(ch=='E')
++x;
if(ch=='W')
--x;
if(ch=='N')
++y;
if(ch=='S')
--y;
}
void insert(pii x,pii y){
auto &s=mp[x];
auto L=s.lower_bound(make_pair(y.first,-INF));
auto R=s.upper_bound(make_pair(y.second+1,INF));
if(L!=s.begin()&&prev(L)->second>=y.first-1)
--L;
if(L==R)
s.insert(y);
else{
int tl=min(L->first,y.first),tr=max(prev(R)->second,y.second);
s.erase(L,R);
s.insert(make_pair(tl,tr));
}
}
void add_range(int x,int y){
int tmp=x/dx;
x-=dx*tmp,y-=dy*tmp;
if(x<0)
--tmp,x+=dx,y+=dy;
insert(make_pair(x,y),make_pair(tmp,tmp+k-1));
}
void prepare(){
mp.clear();
mp[{0,0}].insert(make_pair(0,k-1));
int nowx=0,nowy=0;
for(int i=1;i<=n;++i){
addv(nowx,nowy,a[i]);
add_range(nowx,nowy);
}
}
vector<pii> change(int x,int y){
int flag=0;
if(x==dx)
x-=dx,y-=dy,flag=1;
vector<pii> res;
if(!mp.count(make_pair(x,y)))
return res;
for(auto i:mp[make_pair(x,y)])
res.emplace_back(make_pair(i.first-flag,i.second-flag));
return res;
}
vector<pii> merge(vector<pii> x,vector<pii> y){
vector<pii> res;
auto it=y.begin();
for(auto [l,r]:x){
while(it!=y.end()){
while(it!=y.end()&&it->second<l)
++it;
if(it==y.end()||it->first>r)
break;
res.emplace_back(make_pair(max(it->first,l),min(it->second,r)));
if(it->second>=r)
break;
++it;
}
}
return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
T=1;
while(T--){
cin>>n>>k>>(a+1);
dx=dy=0;
for(int i=1;i<=n;++i)
addv(dx,dy,a[i]);
if(!dx){
swap(dx,dy);
for(int i=1;i<=n;++i){
if(a[i]=='E')
a[i]='N';
else if(a[i]=='N')
a[i]='E';
if(a[i]=='W')
a[i]='S';
else if(a[i]=='S')
a[i]='W';
}
if(!dx)
dx=1,k=1;
}
if(dx<0){
dx=-dx;
for(int i=1;i<=n;++i){
if(a[i]=='E')
a[i]='W';
else if(a[i]=='W')
a[i]='E';
}
}
prepare();
int ans=0;
for(map<pii,set<pii>>::iterator it=mp.begin();it!=mp.end();++it){
int x=it->first.first,y=it->first.second;
for(auto i:merge(merge(change(x,y),change(x+1,y)),merge(change(x,y+1),change(x+1,y+1))))
ans+=i.second-i.first+1;
}
cout<<ans<<'\n';
}
return 0;
}