CodeForce刷题表
Day5 题意: 给定n个数,每个数可能是蓝色也可能是红色,如果是蓝色,那他可以进行-1操作,如果是红色,那他可以进行+1操作。
问能不能让数组1~n每个数都出现一次。
思路: 排序,遍历两遍。
第一遍正向,遇到蓝色就放在最左边,计数器+1,如果这个数小于计数器那么这个数组就不能做到每个数出现一遍。
第二遍逆向,遇到红色就放在最右边,计数器-1,如果这个数大于计数器那么这个数组就不能做到每个数出现一遍。
假设比那里蓝色,如果这个数是2,前面已经有两个数了(计数器为3),由于蓝色只能减不能加,所以这个数就不能起到作用,一共n个数如果少了一个数,那么就不可能同时存在 1~n了。
代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int N = 1e6 +5 ;const ll mod = 1e9 +7 ; struct node { int num; char color; }a[N]; bool cmp (node x,node y) { return x.num < y.num; } int main () { int _;cin>>_; while (_--) { int n; cin>>n; for (int i=1 ;i<=n;i++) cin>>a[i].num; for (int i=1 ;i<=n;i++) cin>>a[i].color; sort (a+1 ,a+1 +n,cmp); int cnt = 1 ; bool k = false ; for (int i=1 ;i<=n;i++) if (a[i].color=='B' ) { if (a[i].num >= cnt) cnt++; else k = true ; } cnt = n; for (int i=n;i>=1 ;i--) if (a[i].color=='R' ) { if (a[i].num <= cnt) cnt--; else k = true ; } if (k) cout<<"NO" ; else cout<<"YES" ; cout<<endl; } return 0 ; }
总结: 倒序思考一点问题都没有。
题意: 给定一个n*m的盘,机器人会根据命令运行,问起点在哪里的时候,可以做的指令最多。
思路: 从头遍历,记录最左端,最右端,最上端,最下端,如果右-左 超过了m或者下-上 超过了 n就退出。
1-w , 1-a就是所需要的
代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <bits/stdc++.h> using namespace std;typedef long long ll;const int N = 1e6 +5 ;const ll mod = 1e9 +7 ; int main () { int _;cin>>_; while (_--) { int n,m; string ss; cin>>n>>m; int w,a,s,d,x,y; w = a = s = d = x = y = 0 ; cin>>ss; int len = ss.size (); for (int i=0 ;i<len;i++) { if (ss[i]=='U' )x--; if (ss[i]=='D' )x++; if (ss[i]=='L' )y--; if (ss[i]=='R' )y++; if (abs (min (w,x)-max (s,x)) >= n || abs (min (a,y)-max (d,y)) >= m ) break ; w=min (w,x);a=min (a,y); s=max (s,x);d=max (d,y); } cout<<1 -w<<" " <<1 -a<<endl; } return 0 ; }
总结: 模拟一下想一下应该是不难解决。
其实还有另外一种做法
代码2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <bits/stdc++.h> using namespace std;int main () { int t; cin>>t; while (t--){ int n,m; cin>>n>>m; string s; cin>>s; int x=1 ,y=1 ; for (int i=s.size ()-1 ;i>=0 ;i--){ if (s[i]=='L' &&x<m)x++; if (s[i]=='R' &&x>1 )x--; if (s[i]=='U' &&y<n)y++; if (s[i]=='D' &&y>1 )y--; } cout<<y<<" " <<x<<endl; } }
单独看左右,倒着找到起始位置,从起始位置可以走最远的路!
上下同样如此。
所以这样的题可以分治成左右和上下两部分来完成,左右能走最远的位置就是y坐标,上下能走最远的位置就是x坐标。