題意:ios
給你一個地圖的大小(1e5*1e5)和操做次數(2e5),每次操做使機器人上下左右移動,若是當前在邊界還要向外走,機器人就會忽略當前操做,spa
要求你給出一個起點,使得被忽略的操做數最少,輸出最少的忽略次數。code
思路:blog
這個題真思路。。首先,上下和左右是徹底獨立的。string
開始我想的是用線段樹維護一個相對起點的位置(維護最值),而後能夠logn找到距離當前位置距離爲地圖大小的下一個操做點,it
而後nlogn預處理出全部的,而後dfs枚舉當前撞兩邊的牆和還在走的座標,過程能夠記憶化,經過預處理,這個複雜度是on的,io
而後就獲得了最小的忽略次數,根據對應的是沒撞牆或者撞牆的操做點,能夠獲得起始座標。class
可是看了幾分別人的代碼。。大致意思就是對於上下或左右,你最多減小的次數就是地圖的長度,你能夠默認當前在最上邊,而後去模擬整個過程,stream
一旦撞到了上牆,起點位置就向下移動一個,撞下牆就表示下面的起點向上移一個,不過不用管,能夠讓撞了地圖長度次牆就結束,map
表示已經避免了最大的撞牆次數了,起點位置已經固定。若是沒有撞牆,那就在最上邊就行了。。
左右徹底相同的思路再寫一遍,而後獲得了起點的座標,模擬一下整個過程就獲得了最小次數了。
/* *********************************************** Author :devil ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <stack> #include <map> #include <string> #include <time.h> #include <cmath> #include <stdlib.h> #define LL long long #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,a,b) for(int i=a;i>=b;i--) #define ou(a) printf("%d\n",a) #define pb push_back #define pii pair<int,int> #define mkp make_pair #define IN freopen("in.txt","r",stdin); #define OUT freopen("out.txt","w",stdout); using namespace std; const int inf=0x3f3f3f3f; const LL INF=0x7f7f7f7f; const int mod=1e9+7; const int N=2e5+10; int t,n,m; char s[N]; int main() { scanf("%d",&t); while(t--) { scanf("%d%d%s",&n,&m,s); int len=strlen(s),x=1,y=1,l=1,r=n,ans=0; for(int i=0;i<len;i++) { if(l==r) break; if(s[i]=='^') { if(l==1) x++; else l--; r--; } else if(s[i]=='v') { l++; if(r<n) r++; } } l=1,r=m; for(int i=0;i<len;i++) { if(l==r) break; if(s[i]=='<') { if(l==1) y++; else l--; r--; } else if(s[i]=='>') { l++; if(r<m) r++; } } for(int i=0;i<len;i++) { if(s[i]=='^') { if(x==1) ans++; else x--; } else if(s[i]=='v') { if(x==n) ans++; else x++; } else if(s[i]=='<') { if(y==1) ans++; else y--; } else if(s[i]=='>') { if(y==m) ans++; else y++; } } printf("%d\n",ans); } return 0; }