记录:又是做得非常糟糕的一场。
一些题明明只需要用简单的写法就行,自己却写了太多判断。
总是着急写题,没有想清楚情况,怎么写?使用什么STL都没有想清楚。
写题时还是一定得理清楚思路:确定好要写什么,怎么写。
同时一些技巧诸如精度之类((x+k-1)/k
)的要多多想起来用。
A
代码
#include <bits/stdc++.h> using namespace std;using ll=long long ;void solve () { int a,b; cin>>a>>b; cout<<b-a<<"\n" ; } int main () { int t=1 ; cin>>t; for (int i=1 ;i<=t;i++) { solve (); } return 0 ; }
B
代码
#include <bits/stdc++.h> using namespace std;using ll=long long ;void solve () { int n; cin>>n; std::vector<string> v (n) ; for (int i = 0 ; i < n; ++i) { cin>>v[i]; } for (int i = n-1 ; i >= 0 ; --i) { for (int j = 0 ; j < v[i].size (); ++j) { if (v[i][j]=='#' ) { cout<<j+1 <<" " ; break ; } } } cout<<"\n" ; } int main () { int t=1 ; cin>>t; for (int i=1 ;i<=t;i++) { solve (); } return 0 ; }
C
这题写了一堆判断,写得很糟糕。
可以使用这个方法:(x+k-1)/k
就可以控制其向上取整。
思路
其实就是分别计算走x
和y
方向需要多少步,取最大值。
如果是x
最大那么,需要减一。
代码
一
#include <bits/stdc++.h> using namespace std;using ll=long long ;void solve () { ll x,y,k; cin>>x>>y>>k; ll ans=0 ; ll a=(x+k-1 )/k,b=(y+k-1 )/k; if (b<a) { cout<<2 *a-1 <<"\n" ; } else cout<<2 *b<<"\n" ; } int main () { int t=1 ; cin>>t; for (int i=1 ;i<=t;i++) { solve (); } return 0 ; }
二
#include <bits/stdc++.h> using namespace std;using ll=long long ;void solve () { ll x,y,k; cin>>x>>y>>k; ll a=x/k+(x%k!=0 ); ll b=y/k+(y%k!=0 ); if (a<=b) cout<<2 *b<<"\n" ; else cout<<2 *a-1 <<"\n" ; } int main () { int t=1 ; cin>>t; for (int i=1 ;i<=t;i++) { solve (); } return 0 ; }
D
也是写得一坨,一定要想清楚用什么STL维护更好,怎么写再开始敲。
思路
不难想到只有四种情况。
---- |\ /\ \------/ \ | | \ / \ \ / \ | | \ / \ \ / \| ---- /------\ \/
针对第一种情况,我们可以维护每一条竖边,然后计算对应的有多少个纵坐标为1
的点即可。第二种情况也是类似。
第三种情况,我们可以枚举直角顶点,然后看看是否存在左右两个顶点,可以用set
进行维护。第四种情况也是类似。
二三情况可以合并,我们可以先用一个vector
维护,另外一四也是如此。
Trick
可以用map
来维护竖边,然后用set
来维护左右顶点是否存在。
代码
#include <bits/stdc++.h> using namespace std;using ll=long long ;void solve () { int n; cin>>n; std::vector<int > x (n) ,y (n) ; std::map<int , int > map; std::vector<int > v0,v1; std::set<int > s0,s1; int cnt0=0 ,cnt1=0 ; for (int i = 0 ; i < n; ++i) { cin>>x[i]>>y[i]; map[x[i]]++; if (y[i]==0 ) { v0.push_back (x[i]); cnt0++; s0.insert (x[i]); } if (y[i]==1 ) { v1.push_back (x[i]); cnt1++; s1.insert (x[i]); } } ll ans=0 ; for (auto x: v0) { if (map[x]==2 ) ans+=1ll *(cnt0-1 ); if (s1.count (x-1 ) && s1.count (x+1 )) ans++; } for (auto x: v1) { if (map[x]==2 ) ans+=1ll *(cnt1-1 ); if (s0.count (x-1 ) && s0.count (x+1 )) ans++; } cout<<ans<<"\n" ; } int main () { int t=1 ; cin>>t; for (int i=1 ;i<=t;i++) { solve (); } return 0 ; }
E
思路
很显然的二分,这里采取的是二分位置。我们可以二分绝对值最小的位置。
分析一下题目:随着i
的增大,那么\(a_1+a_2+a_i-a_{i+1}-······-a_n\) 肯定是越来越大的,那么,原来是负数,会逐渐变为正数,那么我们二分以上式子最接近0的位置即可。
这里的写法是pre>back
返回false
。否则返回true
。
所以最后还需要比较一下l,l-1,l+1
这三个位置对应的各自式子的和,取最小值即可。
代码
#include <bits/stdc++.h> using namespace std;using ll=long long ;void solve () { ll n,k; cin>>n>>k; ll l=1 ,r=n; auto check=[&](ll x) { ll pre=(2 *k+x-1 )*(x)/2 ; ll back=(2 *k+n+x-1 )*(n-x)/2 ; if (pre>back) { return false ; } else { return true ; } }; while (l+1 <r) { ll mid=(l+r)>>1 ; if (check (mid)) { l=mid+1 ; } else { r=mid; } } ll sum1=abs ((2 *k+l-1 )*(l)/2 -(2 *k+n+l-1 )*(n-l)/2 ); l++; ll sum2=abs ((2 *k+l-1 )*(l)/2 -(2 *k+n+l-1 )*(n-l)/2 ); l-=2 ; ll sum3=abs ((2 *k+l-1 )*(l)/2 -(2 *k+n+l-1 )*(n-l)/2 ); cout<<min ({sum1,sum2,sum3})<<"\n" ; } int main () { int t=1 ; cin>>t; for (int i=1 ;i<=t;i++) { solve (); } return 0 ; }
F
思路
不难发现一直重复循环,如果直接计算这个区间,似乎需要很复杂的分类讨论。
排列又是固定,而且是多次询问,所以考虑可以先离线处理。
利用数位dp
的常用方法(其实就是前缀和)直接获取那段区间的结果(query(r)-query(l-1)
)。
接下来就考虑处理query(r)
这部分。手写几个例子可以发现,可能会出现312这样的情况。所以需要分类讨论。
记x
为总共经过的完整区间(也就是偏移量),y
就是剩余的个数。
如果x+y<=n
,说明最大的一个元素(最初是123456,后面不断偏移234567
345678等等)没有越界。直接使用前缀和计算即可。
反之,说明越界。(如312中的31这种情况)。那么可以拆成两部分处理(对应就是3和1),直接sum[x+y-n]
,得到的就是越界范围的数值(对应1)。
sum[n]-sum[x]
就是正常范围的数字(对应3).
代码
#include <bits/stdc++.h> using namespace std;using ll=long long ;void solve () { int n,q; cin>>n>>q; std::vector<ll> a (n) ,sum (n+1 ,0 ) ; for (int i = 0 ; i < n; ++i) { cin>>a[i]; sum[i+1 ]=sum[i]+a[i]; } auto query=[&](ll m) { ll x=m/n; ll y=m%n; ll ans=sum[n]*x; if (y) { if (x+y<=n) { ans+=sum[x+y]-sum[x]; } else { ans+=sum[x+y-n]+sum[n]-sum[x]; } } return ans; }; while (q--) { ll l,r; cin>>l>>r; cout<<query (r)-query (l-1 )<<"\n" ; } } int main () { int t=1 ; cin>>t; for (int i=1 ;i<=t;i++) { solve (); } return 0 ; }