A - Largest Submatrix of All 1’s
题意:给一个只包含0和1的n*m的矩形,求由‘1’围成的最大矩形的面积。
分析:单调栈的应用,对n行每一行处理,可转化为POJ - 2559求最大矩形的面积。注意点:如果加入的元素破坏了非单调递减,清栈之后要把栈顶元素值更新为新加入的元素。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 2005; 6 typedef long long ll; 7 int nums[maxn][maxn]; 8 int st[maxn]; 9 int main(){ 10 int n,m; 11 while (~scanf("%d%d",&n,&m)){ 12 memset(nums,0,sizeof nums); 13 for (int i = 1; i <= n; i++){ 14 for (int j = 1; j <= m; j++){ 15 scanf("%d",&nums[i][j]); 16 } 17 } 18 for (int i = 1; i <= n; i++){ 19 for (int j = 1; j <= m; j++){ 20 if (nums[i][j]) nums[i][j] += nums[i-1][j]; 21 } 22 } 23 ll s = 0; 24 for (int i = 1; i <= n; i++){ 25 int top = 0; 26 memset(st,0,sizeof st); 27 nums[i][m+1] = -1; 28 for (int j = 1; j <= m+1; j++){ 29 if (top == 0 || nums[i][j] >= nums[i][st[top-1]]) { 30 st[top++] = j; 31 } 32 else{ 33 int pos; 34 while (top && nums[i][st[top-1]] > nums[i][j]){ 35 pos = st[top-1]; 36 s = max(s,(ll)(j-st[top-1])*(ll)nums[i][st[top-1]]); 37 top--; 38 } 39 st[top++] = pos; 40 nums[i][pos] = nums[i][j];//关键点 41 } 42 } 43 } 44 printf("%lld ",s); 45 } 46 return 0; 47 }
B - Ayoub's function
题意:给一个长度为n的01串,含有m个1,求如何组合能使含1子区间数最多,输出最多数量。
分析:总含1子区间数 = 总子区间数 - 总连续0子区间数,要使答案最大,总连续0子区间数要最少。最优方案(不作证明)是把所有0均分区间,注意:剩下的0不能全部给一个区间,也要均分到每个区间。此外当m>=n/2时最优解一定为0和1交替分配,剩下的1随意分配,可以直接计算得答案减少一半的枚举次数。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 int T; 6 ll n, m; 7 scanf("%d", &T); 8 while (T--) { 9 scanf("%lld%lld",&n,&m); 10 if (m==0) puts("0"); 11 else if (m>=(n/2)){ 12 printf("%lld ",m+(n-1)*n/2); 13 } 14 else{ 15 ll nums = (n-m)/(m+1),l = (n-m)%(m+1); 16 printf("%lld ",n*(n+1)/2-l*(nums+1)*(nums+2)/2+(m+1-l)*nums*(nums+1)/2); 17 } 18 } 19 return 0; 20 }
C - Managing Difficulties
题意:求数组中任意三个数构成等差数列的组数。
分析:枚举起点、中点、终点之中任意2个,理论上通过这两个点可以推得第三个数,只需查询并统计所有第三个数的数量。给的时间2s,组数 t <= 10,n <= 2000,枚举两个点需要O(n^2)的复杂度,单看n时间是足够的,但数组中的数可以达到1e9,有些方案使用map可以卡着时间过,但注意到n只有2000,十分明显可以离散化处理优化时间复杂度,离散化后对该题给的数据时间可以降低3倍以上,但使用离散化对枚举的点有特殊要求,具体看代码实现。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn = 2005; 4 typedef long long ll; 5 int ans,m,n,t; 6 ll arr[maxn],a[maxn],b[maxn]; 7 int mp[maxn]; 8 inline ll read() { 9 char ch = getchar(); ll x = 0, f = 1; 10 while(ch < '0' || ch > '9') { 11 if(ch == '-') f = -1; 12 ch = getchar(); 13 } while('0' <= ch && ch <= '9') { 14 x = x * 10 + ch - '0'; 15 ch = getchar(); 16 } return x * f; 17 } 18 int get(ll x){ 19 int pos = lower_bound(b+1,b+1+m,x)-b; 20 if (b[pos]!=x) pos = 0; 21 return pos; 22 } 23 int main(){ 24 scanf("%d",&t); 25 while (t--){ 26 ans = 0,m = 0; 27 scanf("%d",&n); 28 for (int i = 1; i <= n; i++){ 29 a[i] = b[i] = read(); 30 } 31 sort(b+1,b+1+n); 32 m = unique(b+1,b+1+n)-b-1; 33 for (int i = 1; i <= n ;i++) 34 arr[i] = lower_bound(b+1,b+1+m,a[i])-b,mp[arr[i]]++; 35 36 for (int i = 1; i <= n; i++){ 37 mp[arr[i]]--; 38 for (int j = i+1; j <= n; j++){ 39 mp[arr[j]]--; 40 ll tmp = 2*a[j]-a[i]; 41 if (tmp>=1&&tmp<=b[m]) ans += mp[get(tmp)]; 42 } 43 for (int j = i+1; j <= n; j++) mp[arr[j]]++; 44 } 45 for (int i = 0; i <= m; i++) mp[i] = 0; 46 printf("%d ",ans); 47 } 48 return 0; 49 }
F - Binary String Minimizing
题意: 给一个长度为n的01串,能够把相邻的两个数交换k次,输出交换完后最小字典序的01串。
分析:把0尽可能往前放,可以从字符串第一个位置开始枚举,只要移动次数够就把0移到那个位置,不够就往前移剩余移动次数次。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main(){ 5 string str; 6 ll q,k,n; 7 cin>>q; 8 while (q--){ 9 cin>>n>>k>>str; 10 ll cnt = 0; 11 for (ll i = 0; i < n; i++){ 12 if (str[i] == '0'){ 13 if (i-cnt <= k) k -= i-cnt,swap(str[i],str[cnt++]); 14 else swap(str[i],str[i-k]),k = 0; 15 } 16 if (!k) break; 17 } 18 cout<<str<<endl; 19 } 20 return 0; 21 }
H - A Simple Math Problem
题意:给a,b,找满足条件x+y = a,lcm(x,y)= b的x、y,找不到输出No Solution。
分析:lcm(x,y) = x * y / gcd(x,y) = b 易证 gcd(a,b) = gcd(x,y),2个未知数2个方程可以直接把x和y算出来,如果不是整数输出No Solution即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 inline ll gcd(ll a, ll b) { 5 return b == 0 ? a : gcd(b, a%b); 6 } 7 int main(){ 8 ll a,b,X,Y; 9 while (~scanf("%lld %lld",&a,&b)){ 10 double y = (a-sqrt(a*a-4*b*gcd(a,b)))/2; 11 if (y == (ll)y) { 12 Y = y; 13 if (Y <= a-Y) 14 printf("%lld %lld ",Y,a-Y); 15 else 16 printf("%lld %lld ",a-Y,Y); 17 } 18 else printf("No Solution "); 19 } 20 return 0; 21 }