A题.Reverse
签到题,贪心+stl运用直接过.
抓住核心:最高位最大就行.
#include<bits/stdc++.h>
using namespace std;
int p[1020],a[1020];
int n;
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
int n;
while(t--){
cin>>n;
int x;
for(int i=1;i<=n;i++){
cin>>x;
a[i]=x;
p[x]=i;
}
for(int i=1;i<=n;i++){
if(p[i]==i){
int flag=1;
continue;
}
reverse(a+i,a+p[i]+1);
break;
}
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
cout<<"\n";
}
}
B. Odd Swap Sort
注意到只有两个数奇偶性不同才能互相交换位置。分别考虑奇数列和偶数列情况。
如果奇数列或偶数列中有逆序存在,则原数列肯定不可能能够通过交换元素位置,达到非递减数列。
#include<bits/stdc++.h>
using namespace std;
vector<int>o,e;
int t,n;
int main()
{
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>n;
o.clear();
e.clear();
for(int i=0;i<n;i++){
int x;
cin>>x;
if(x%2!=1)o.push_back(x);
else e.push_back(x);
}
int l1=o.size();
int l2=e.size();
int flag=1;
for(int i=1;i<l1;i++)if(o[i]<o[i-1]){
cout<<"No\n";
flag=0;
break;
}
if(flag==0)continue;
for(int i=1;i<l2;i++)if(e[i]<e[i-1]){
cout<<"No\n";
flag=0;
break;
}
if(flag==0)continue;
cout<<"Yes\n";
}
}
C题.Inversion Graph
个人觉得挺好的一道题,题意大概就是找连通分量(connected components)的个数;虽然好像是个图论题,但其实只是用了图论的概念,本质其实就是个数据结构题。为什么这么说呢,由于只要两个数下标递增,值递减(即i<j,pi>pj即可建边)那么在寻找连通分量的时候,最直接的感觉就是一个最大的数会统治一个区间,最后统计这些数(或者区间数即可);但是感觉是需要经过打磨和落地的,那么配合样例来看一下。
首先这个显然为3,(搭个地基或者开个头)这里的基本算法思路就是当我们维护一个数组时,只要一直递增就一直计数。1 2 3 4 为4个 1 2 3 4 5 6为6个。当然没这么简单。
下一个样例我们发现,按照之前的思路还是可以做的,就是要做一点改动,就是我们由于我们要统计个数,先假设每个区间不互相干涉,所以只要留每个区间的max即可,最后统计一下个数就行。状态需要保留,要回溯要剔除(pop)自然而然会联想到stack这种数据类型。那么框架又更搭的更进一步了
stack<int> s;
for(....)
cin>>x;
if(!s.empty()&&s.top()>x){
....
}
s.push_back(x); //也就是说只要s非空或者输入的x>栈顶元素,那么就往里压,使得s.top()一直是max
问题又来了,那如果是这样子的该怎么办,也就是说我们之前的方法不能正确的找到一个最大值统领的区域。原方法是3 5;但其实只有一个。也就是说5通过2联通了3,所以要把堆栈中的3剔除(pop)。如何实现呢,那么自然,把2想成一个通道,即如果x这个值小于5,那么还需要跟3比,如果小于3,那么相当于3跟5联通,那么3被提出。
把以上思路普遍化,就是当x<top()时,x不能不管了,要继续往下检查,如果x<s(某个值)。那么s就是被联通的,s.pop();再调试一下,就是以下解法:
AC代码:
#include <bits/stdc++.h>
using namespace std;
int t,n,i,x,y;
int main()
{
ios::sync_with_stdio(0);cin.tie(0);
cin>>t;
while (t--)
{
cin>>n;
stack<int> s;
while (n--)
{
cin>>x;y=x;
if (!s.empty()&&s.top()>x)
{
y=s.top();s.pop();
while (!s.empty()&&s.top()>x) s.pop();
}
s.push(y);
}
cout<<s.size()<<'\n';
}
}
总结:要体会思路搭建的感觉,算法就是思路,有逻辑地思考问题,抽丝剥茧再加以变现,同时联想结构,结构是很重要的. 怎么吃一个问题,是我们需要学习的.问题真的会有很多吃法.
D. Big Brush
大概思路就是逆推,从最后开始,把大小为2X2一样色的换成0。0是万能色,不断倒推,最后顺着压栈输出。
#include <bits/stdc++.h>
using namespace std;
const int mxn = 1e3 + 10;
const int mx = 1e6 + 10;
int g[mxn][mxn], n, m, sum, cnt, ans[3][mx];
void dfs(int x, int y) {
if(x < 1 || y < 1 || x >= n || y >= m) return;
int p = 0;
for(int i = x; i <= x + 1; i ++)
for(int j = y; j <= y + 1; j ++) {
if(!p && g[i][j]) p = g[i][j];
if(p && p != g[i][j] && g[i][j]) return;
}
if(!p) return;
ans[0][++ cnt] = x, ans[1][cnt] = y, ans[2][cnt] = p;
for(int i = x; i <= x + 1; i ++)
for(int j = y; j <= y + 1; j ++)
if(g[i][j]) sum ++, g[i][j] = 0;
for(int i = x - 1; i <= x + 1; i ++)
for(int j = y - 1; j <= y + 1; j ++) {
if(i == x && j == y) continue;
dfs(i, j);
}
}
int main() {
ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i ++) for(int j = 1; j <= m; j ++) cin >> g[i][j];
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++) {
if(g[i][j] == g[i + 1][j + 1] && g[i][j] == g[i][j + 1] && g[i][j] == g[i + 1][j] && g[i][j])
dfs(i, j);
}
if(sum == n * m) {
printf("%d\n", cnt);
for(int i = cnt; i >= 1; i --)
printf("%d %d %d\n", ans[0][i], ans[1][i], ans[2][i]);
}
else cout << -1 <<"\n";
return 0;
}
第一次过1500,记录一下,情人节晚上打的.虽然运气成分很大,但也希望以后能越来越好.争取进队!