A. Bad Triangle
题目:https://codeforces.com/contest/1398/problem/A
题解:一道计算几何题,只要观察数组的第1,2,n个,判断他们能否构成三角形即可。
必须注意:从反方向判断时要注意:两边之和大于第三边的反向是:a[1]+a[2]<=a[n]一定注意为小于等于,两边之差小于第三边的反义是:a[n]-a[2]>=a[1]切记注意是大于等于
代码:
#includeusing namespace std; typedef long long ll; const int N=50010; ll t,n; ll a[N]; int main() { ll i,j,k; cin>>t; while(t--) { bool flag=true; cin>>n; for(i=1;i<=n;i++) cin>>a[i]; if(a[1]+a[2]<=a[n]||a[n]-a[2]>=a[1]) cout<<"1 2 "< else cout<<"-1"<<endl; } return 0; }endl;
B. Substring Removal Game
题目:https://codeforces.com/contest/1398/problem/B
题解:一到关于字符串的贪心问题,由于我们要1的个数最大,所以只要找相邻的1的个数就好,存到数组后进行排序,由于我们是先手,因此每隔一个取一次。
代码:
#includeusing namespace std; int a[110]; bool cmp(int a,int b) { return a>b; } int main() { int i,t; string s; cin>>t; while(t--) { cin>>s; int len=s.length(); int k=0; int j=0; for(i=0;i if(s[i]=='1') k++; else { if(k!=0) { a[j++]=k; k=0; } } } if(k!=0) a[j++]=k; int ans=0; sort(a,a+j,cmp); for(i=0;i) { ) { if(i%2==0) ans+=a[i]; } cout< endl; } return 0; }
C. Good Subarrays
题目:https://codeforces.com/contest/1398/problem/C
题解:我认为这道题是最难想的,一开始用暴力,TLE在第三组数据。因而不能用这种方法。
在线处理的方法。
我们想想,用子数组总和减去元素个数,如果是为0,那么就是好子数组,如果好子数组中又包含好子数组呢?那么该好子数组是不是可以分为三个好子数组。
如果不为0呢?那么我们是不是可以记录这个状态,我们继续往后探索的的时候突然发现子数组总和减去元素个数又为我们上次记录过的状态。那么这个子数组是不是可以拆成我们上次记录过的状态子数组和另一个子数组减元素个数为0的好子数组?(仔细思考这里,非常重要!)
那么我们层层深入,如果一个子数组能这样分为我们已经访问过的状态子数组和一个好子数组,那么不就实现在线处理了吗?因为现在我们只要遍历一遍数组了,其他的子数组我们就可以利用当前已经记录的子数组分解获得。那么时间复杂度就大大减小了。
那么我们怎么记录之前状态呢?这里就要使用map容器了,我们标记所有计算的差值状态,利用ans统计值即可。若之前标记过两次,说明我们可以拆成两种情况:一个差值为标记过的子数组和一个好子数组
代码:
#include//POJ不支持 #define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增 #define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。 #define pb push_back #define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) #define fi first #define se second #define mp make_pair using namespace std; const int inf = 0x3f3f3f3f;//无穷大 const int maxn = 1e5;//最大值。 typedef long long ll; typedef long double ld; typedef pair return 0; }pll; typedef pair<int, int> pii; //*******************************分割线,以上为自定义代码模板***************************************// int main() { IOS; int t,n,i,j; string str; cin>>t; while(t--) { cin>>n; cin>>str; ll ans=0,num=0; map<int,ll>mp; mp[0]=1;//当差值为0时就是一个好数组 rep(i,0,n-1) { num+=str[i]-'0';//计算前缀和数组 ans+=mp[num-(i+1)];//加上当前的状态对应的值 mp[num-(i+1)]++;//记录上标记一次 //其实好与坏的区别就在于第一个是好还是坏 } cout< endl; }
D. Colored Rectangles
题目:https://codeforces.com/contest/1398/problem/D
题解:DP题,我们来思考一下他们的状态转移,设我们可以构造的最大矩形数为nnn,(注意:最大矩形数是一定固定的)那么该状态的最优解是不是可以转换为矩形数为n−1n-1n−1的最优解+当前可构建矩形面积的最大值。我们用dp[i][j][k]表示用去了i个R颜色彩棒,j个G个颜色彩棒,k个C颜色彩棒,那么我们表示矩形数为n−1自然对应的彩棒数要减2了,这里注意有三种情况都要判断
需要注意的是必须对其进行排序,因为我们相当于是不断加入三根彩棒,比较当时拥有的彩棒合成矩形最大值,这就是一个矩形的最优解,再往后推,逐渐得到总矩形的最优解
代码:
#include//POJ不支持 #define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增 #define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。 #define pb push_back #define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0) #define fi first #define se second #define mp make_pair using namespace std; const int inf = 0x3f3f3f3f;//无穷大 const int maxn = 210;//最大值。 typedef long long ll; typedef long double ld; typedef pair return 0; }pll; typedef pair<int, int> pii; ll dp[maxn][maxn][maxn]; int r[maxn],g[maxn],b[maxn]; int main() { IOS; int R,G,B,i,j,k; cin>>R>>G>>B; rep(i,0,R-1) cin>>r[i]; rep(i,0,G-1) cin>>g[i]; rep(i,0,B-1) cin>>b[i]; //排序 sort(r,r+R); sort(g,g+G); sort(b,b+B); rep(i,0,R) { rep(j,0,G) { rep(k,0,B) { if(i&&j) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+r[i-1]*g[j-1]); if(i&&k) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]+r[i-1]*b[k-1]); if(j&&k) dp[i][j][k]=max(dp[i][j][k],dp[i][j-1][k-1]+g[j-1]*b[k-1]); } } } cout< endl;