题目链接
A题
题解
知道了单调栈,那么第一题就很好解决了,就是两个串到每个位置都比较一下前面的最小值的下标是否相等(用单调栈来实现--后面讲),如果相等则继续,如果都没有找到就是都是自己最小,也用单调栈处理成为相等,如果遇到不相等,那么i-1就是题目所要求出来的k的值
补充
单调栈
单调栈的一大优势就是线性的时间复杂度,所有的元素只会进栈一次,而且一旦出栈后就不会再进来了。
单调递增栈可以找到左起第一个比当前数字小的元素。比如数组 [2 1 4 6 5],刚开始2入栈,数字1入栈的时候,发现栈顶元素2比较大,将2移出栈,此时1入栈。那么2和1都没左起比自身小的数字。然后数字4入栈的时候,栈顶元素1小于4,于是1就是4左起第一个小的数字。此时栈里有1和4,然后数字6入栈的时候,栈顶元素4小于6,于是4就是6左起第一个小的数字。此时栈里有1,4,6,然后数字5入栈的时候,栈顶元素6大于5,将6移除,此时新的栈顶元素4小于5,那么4就是5左起的第一个小的数字,最终栈内数字为 1,4,5。
/* L是输出端,然后s是辅助数组,c是源数组 */ void solve(int* c, int* L) { int top = 0; s[0] = node{0, 0}; for(int i = 1; i <= n; i++) { /*找到向左走第一个比它小的数 */ while(top && s[top].val >= c[i]) top--; L[i] = s[top].id; s[++top] = node{i, c[i]}; } }
参考链接:
https://www.cnblogs.com/grandyang/p/8887985.html
AC代码
代码是队友写的,orz
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn = 100000 + 5; struct node { int id; int val; }; int a[maxn], b[maxn]; int l1[maxn], l2[maxn]; node s[maxn]; int n; /* L是输出端,然后s是辅助数组,c是源数组 */ void solve(int* c, int* L) { int top = 0; s[0] = node{0, 0}; for(int i = 1; i <= n; i++) { /*找到向左走第一个比它小的数 */ while(top && s[top].val >= c[i]) top--; L[i] = s[top].id; s[++top] = node{i, c[i]}; } } int main() { while(~scanf("%d", &n)) { for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) scanf("%d", &b[i]); solve(a, l1); solve(b, l2); int ans = n; for(int i = 1; i <= n; i++) { if(l1[i] != l2[i]) { ans = i-1; // ans = n-1; break; } } printf("%d\n", ans); } return 0; }
B题
C题,D题
能力有限,战略计划原因没有补这两题
C题解推荐
E题
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define MAXN 2000 #define MOD 1000000007 int n,m; int dp[MAXN+5][MAXN+5]; int main() { while(~scanf("%d%d",&n,&m)){ for(int i=0;i<=n+m;i++) for(int j=0;j<=n+m;j++) dp[i][j]=0; dp[0][0]=1; for(int i=0;i<=n+m;i++) for(int j=0;j<=n+m;j++){ if(i+1<=j+n&&j<=i+m) dp[i+1][j]=(dp[i+1][j]+dp[i][j])%MOD; if(i<=j+n&&j+1<=i+m) dp[i][j+1]=(dp[i][j+1]+dp[i][j])%MOD; } printf("%d\n",dp[n+m][n+m]); } }
F
图片以及思路转载+少量整理+感谢
借鉴两位大佬的思路和博文进行整理的,感谢
Izayoi_w
WAautomaton
题目要求36*E,而E = (22/36) * S,所以ans = 22 * S
关于三角形的面积,已知三个顶点坐标,我们可以用叉积来求,如ΔABC,S = (1/2) * ( 向量(AB) ✖ 向量(AC) )。
这里要注意,叉积有正有负,最终的答案为11倍叉积的绝对值。
AC代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn = 100000 + 5; int main() { ll x1, y1, x2, y2, x3, y3; while(cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3) { ll res = 11*((x1-x2)*(y3-y2)-(y1-y2)*(x3-x2)); if(res < 0) res = -res; cout << res << endl; } return 0; }
G,H,I因己太菜先留坑
J
题解
解法一: 直接交叉相乘
解法二: 直接看出题人叉姐的解法
AC代码
#include <iostream> #include <cstdio> using namespace std; typedef __int128 ll; int main() { long long x, a, y, b; while (scanf("%lld %lld %lld %lld", &x, &a, &y, &b) != EOF) { ll p = x; p *= b; ll q = y; q *= a; if (p > q) printf(">\n"); else if (p == q) printf("=\n"); else printf("<\n"); } return 0; }