Hackerrank 2020 February 2014 解题报告
比赛链接
Sherlock and Watson (20分)
题意:给定一个数组,向右平移K次,然后有Q个询问,问第x位置上是几
做法:直接模拟即可

1 #include <iostream> 2 using namespace std; 3 int n,k,q; 4 int a[ 100100 ],b[ 100100 ]; 5 int main(){ 6 ios::sync_with_stdio( 0 ); 7 cin>>n>>k>> q; 8 for ( int i= 0 ;i<n;i++ ){ 9 cin>> a[i]; 10 } 11 for ( int i= 0 ;i<n;i++ ){ 12 b[(i+k)%n] = a[i]; 13 } 14 int x; 15 for ( int i= 0 ;i<q;i++ ){ 16 cin>> x; 17 // int tar = (x+k)%n; 18 cout<<b[x]<< endl; 19 } 20 return 0 ; 21 }
Make it Anagram ( 30分 )
题意:给定两个字符串,问删除多少字符后两个串所含的字符以及对应的个数相同
做法:分别统计每个字符在两个串中出现的次数,统计差值并求和就是答案

1 #include <cmath> 2 #include <cstdio> 3 #include <vector> 4 #include <iostream> 5 #include <algorithm> 6 #include < string > 7 using namespace std; 8 9 int p[ 255 ],q[ 255 ]; 10 int main() { 11 /* Enter your code here. Read input from STDIN. Print output to STDOUT */ 12 string a,b; 13 cin>>a>> b; 14 for ( char x:a){ 15 p[x]++ ; 16 } 17 for ( char x:b){ 18 q[x]++ ; 19 } 20 int ans = 0 ; 21 for ( int i= ' a ' ;i<= ' z ' ;i++ ){ 22 int tmp = p[i]- q[i]; 23 if (tmp< 0 )tmp=- tmp; 24 ans+= tmp; 25 } 26 cout<<ans<< endl; 27 return 0 ; 28 }
Cutting boards ( 40分 )
题意:有一个M*N的木板,要把它分成M*N个单位块。每次可以沿横向或纵向切割,连续切割的代价为x1,x2,x..n和y1,y2...yn。求完成任务的最小代价和。
做法:既然所有的链接处都要被切开,那么就优先切代价高的,这样可以减少连续切割的次数,总之就是贪心了。

1 #include <cmath> 2 #include <cstdio> 3 #include <vector> 4 #include <iostream> 5 #include <algorithm> 6 #include <functional> 7 using namespace std; 8 typedef long long ll; 9 const ll mod = (ll)1e9+ 7 ; 10 ll m,n,x[ 1000001 ],y[ 1000001 ]; 11 int main() { 12 ios::sync_with_stdio( 0 ); 13 int t; 14 cin>> t; 15 while (t-- ){ 16 cin>>m>> n; 17 for ( int i= 0 ;i<m- 1 ;i++ ) 18 cin>> x[i]; 19 for ( int i= 0 ;i<n- 1 ;i++ ) 20 cin>> y[i]; 21 sort(x,x+m- 1 ,greater<ll> ()); 22 sort(y,y+n- 1 ,greater<ll> ()); 23 ll ans = 0 ,a= 0 ,b= 0 ; 24 while (a<m- 1 || b<n- 1 ){ 25 if (a<m- 1 ){ 26 if (b<n- 1 ){ 27 if (x[a]> y[b]){ 28 ans = (ans+x[a]*(b+ 1 ))% mod; 29 a++ ; 30 } else { 31 ans = (ans+y[b]*(a+ 1 ))% mod; 32 b++ ; 33 } 34 } else { 35 ans = (ans+x[a]*(b+ 1 ))% mod; 36 a++ ; 37 } 38 } else { 39 ans = (ans+y[b]*(a+ 1 ))% mod; 40 b++ ; 41 } 42 } 43 cout<<ans<< endl; 44 } 45 return 0 ; 46 }
Bike Racers (60分)
题意:城市里有N个自行车手和M个自行车,现在要组织K个人比赛,需要他们都找到一辆车,车手的运动速度为1。求最少能在多少时间使得所有车手都到达所选的车?
做法:随着时间限制的增加,能够到达的车手一定是不减小的,因此我们可以二分时间t,转化为判定问题。显然车和人构成一个二分图,对于能够在时限内走到的,我们建一条边。然后对这个二分图做最大匹配,看是否有k个匹配。总复杂度O(N^3lg(N))。

1 #include <cmath> 2 #include <cstdio> 3 #include <vector> 4 #include <iostream> 5 #include <algorithm> 6 #include <cstring> 7 using namespace std; 8 typedef long long ll; 9 const ll MAXN = 510 ; 10 ll n,m,k; 11 ll a[MAXN][ 2 ],b[MAXN][ 2 ]; 12 struct node{ 13 ll u,v; 14 ll dis; 15 bool operator <( const node& r) const { 16 return dis< r.dis; 17 } 18 }data[MAXN* MAXN]; 19 ll uN,vN; 20 ll g[MAXN][MAXN]; 21 ll linker[MAXN]; 22 bool used[MAXN]; 23 bool dfs(ll u) 24 { 25 ll v; 26 for (v= 0 ;v<vN;v++ ) 27 if (g[u][v]&&! used[v]) 28 { 29 used[v]= true ; 30 if (linker[v]==- 1 || dfs(linker[v])) 31 { 32 linker[v]= u; 33 return true ; 34 } 35 } 36 return false ; 37 } 38 ll hungary() 39 { 40 ll res= 0 ; 41 ll u; 42 memset(linker,- 1 , sizeof (linker)); 43 for (u= 0 ;u<uN;u++ ) 44 { 45 memset(used, 0 , sizeof (used)); 46 if (dfs(u)) res++ ; 47 } 48 return res; 49 } 50 ll calc(ll x){ 51 memset(g, 0 , sizeof (g)); 52 for (ll i= 0 ;i<=x;i++ ){ 53 ll x = data[i].u; 54 ll y = data[i].v; 55 g[x][y] = 1 ; 56 } 57 return hungary(); 58 } 59 ll solve(){ 60 ll cnt = 0 ; 61 uN = n; 62 vN = m; 63 for (ll i= 0 ;i<n;i++ ){ 64 for (ll j= 0 ;j<m;j++ ){ 65 data[cnt].u= i; 66 data[cnt].v= j; 67 data[cnt].dis = (a[i][ 0 ]-b[j][ 0 ])*(a[i][ 0 ]-b[j][ 0 ])+(a[i][ 1 ]-b[j][ 1 ])*(a[i][ 1 ]-b[j][ 1 ]); 68 cnt++ ; 69 } 70 71 } 72 // cout<<"cnt="<<cnt<<endl; 73 sort(data,data+ cnt); 74 /// / for(ll i=0;i <cnt;i++) 75 // cout <<i<<":"<<data[i].dis<<endl; 76 ll lb=-1,ub=cnt; 77 while (ub-lb> 1 ){ 78 ll mid = (ub+lb)/ 2 ; 79 // cout<<mid<<" "<<calc(mid)<<endl; 80 if (calc(mid)>= k){ 81 ub = mid; 82 } else { 83 lb = mid; 84 } 85 } 86 return data[ub].dis; 87 } 88 int main() { 89 ios::sync_with_stdio( 0 ); 90 cin>>n>>m>> k; 91 for (ll i= 0 ;i<n;i++)cin>>a[i][ 0 ]>>a[i][ 1 ]; 92 for (ll i= 0 ;i<m;i++)cin>>b[i][ 0 ]>>b[i][ 1 ]; 93 ll ans = solve(); 94 cout<<ans<< endl; 95 return 0 ; 96 }
Library Query(80分)
题意:带单点修改的区间第k大
做法:因为数据很小(1 <= N <= 10 4 ,1 <= Q <= 10 4 ),直接分块就行。修改的时候暴力对相应的块进行排序,复杂度O(sqrt(n)*lg(n))。查询的时候通过二分转化为判断一个数是第几大的问题,由于中间部分每个块内都是排好序的,二分就可以了,对于边界上的两块或者一块直接暴力统计。复杂度O(sqrt(n)*lg(n)*lg(n))。

1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <vector> 5 #include < set > 6 #include <queue> 7 #include < set > 8 #include <map> 9 #include <cstring> 10 #include <functional> 11 #include <cmath> 12 typedef long long ll; 13 using namespace std; 14 int n,q,cmd,x,y,k; 15 int a[ 10100 ]; 16 int lsize = 128 ; 17 vector< int > v[ 2000 ]; 18 int maxid; 19 int solve( int x, int y, int target){ 20 int idx = x/lsize,idy=y/ lsize; 21 // cerr<<"idx="<<idx<<" idy="<<idy<<endl; 22 int ans = 0 ; 23 for ( int i=x;i<lsize*(idx+ 1 );i++ ){ 24 if (a[i]<= target) 25 ans++ ; 26 } 27 for ( int i=idy*lsize;i<=y;i++ ){ 28 if (a[i]<= target) 29 ans++ ; 30 } 31 for ( int i=idx+ 1 ;i<=idy- 1 ;i++ ){ 32 if (target < v[i][ 0 ]) 33 continue ; 34 else if (target >= v[i].back()) 35 ans+= v[i].size(); 36 else 37 { 38 int tmp = upper_bound(v[i].begin(),v[i].end(),target)- v[i].begin(); 39 ans+= tmp; 40 } 41 42 } 43 return ans; 44 } 45 int main(){ 46 // freopen("int.txt","r",stdin); 47 // freopen("out1.txt","w",stdout); 48 ios::sync_with_stdio( 0 ); 49 int cs; 50 cin>> cs; 51 while (cs-- ){ 52 cin>> n; 53 // lsize = (int)sqrt(n); 54 for ( int i= 0 ;i<=n/lsize;i++ ) 55 v[i].clear(); 56 for ( int i= 0 ;i<n;i++ ) 57 cin>> a[i]; 58 maxid = 0 ; 59 for ( int i= 0 ;i<n;i++ ){ 60 int id = i/ lsize; 61 maxid = id+ 1 ; 62 v[id].push_back(a[i]); 63 } 64 for ( int i= 0 ;i<maxid;i++ ){ 65 sort(v[i].begin(),v[i].end()); 66 } 67 cin>> q; 68 // cout<<"q="<<q<<endl; 69 while (q-- ){ 70 cin>> cmd; 71 if (cmd == 1 ){ 72 cin>>x>> k; 73 x-- ; 74 a[x] = k; 75 int id = x/ lsize; 76 v[id].clear(); 77 for ( int i=id*lsize;i<n&&i<(id+ 1 )*lsize;i++ ){ 78 v[id].push_back(a[i]); 79 } 80 sort(v[id].begin(),v[id].end()); 81 } else { 82 cin>>x>>y>> k; 83 x-- ; 84 y-- ; 85 int idx = x/lsize,idy = y/ lsize; 86 if (idx == idy){ 87 vector< int > tmp(a+x,a+y+ 1 ); 88 sort(tmp.begin(),tmp.end()); 89 cout<<tmp[k- 1 ]<< endl; 90 } else { 91 int lb = - 1 ,ub= 1001 ; 92 while (ub-lb> 1 ){ 93 int mid = (ub+lb)/ 2 ; 94 int rank = solve(x,y,mid); 95 // cerr<<"mid="<<mid<<" rank="<<rank<<endl; 96 if (rank >= k){ 97 ub = mid; 98 } else { 99 lb = mid; 100 } 101 } 102 cout<<ub<< endl; 103 } 104 } 105 } 106 } 107 return 0 ; 108 }