写在前面
时间于6.28-6.30开了一场专题训练,将自己的思路与过程写在下面,以有效监督自己,提高效率,好好反思。
题解
A-Time to Raid Cowavans
div1D题劝退 待补
B-A and B and Compilation Errors
思路:在第一行所有出现的n个数字中,在map中全部+2,因为你剩下两行是你取出一个a,再取出一个b,那么a以后不会在出现(这里出现不是这个数字,而是取出的那个特殊的,因为会有重复的),b会在第二行出现一次,第三行不会出现。所以:我们在接下来两行每次出现就-1,看还剩下什么。
#include<bits/stdc++.h>
using namespace std;
const int N = 100007;
int n,a[N],ans1,ans2,x;
map<int,int> mp;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i];
mp[a[i]]+=2;
}
for (int i=1;i<n;i++)
{
cin>>x;
mp[x]--;
}
for (int i=1;i<n-1;i++)
{
cin>>x;
mp[x]--;
}
for (int i=1;i<=n;i++)
{
if (mp[a[i]]==1) ans2=a[i];
if (mp[a[i]]==2) ans1=a[i];
if (mp[a[i]]>2) ans1=ans2=a[i];//可能会有重复的 都为一个数字
}
cout<<ans1<<endl<<ans2;
}
/*
3 3 3
2 2 2
2 1 1
2 1 0
*/
C - Color the Fence
思路:不能全为贪心,加入v=15,'1'需要4,'5'需要5,‘9'需要6,如果是贪心,那么只会有“111”,但是同样用5的话,也不行,因为我可以在“555”的基础上,减少最后一位的’5‘,让其变成’1‘,这样就多出来了一个可以将最左边的’5‘换成’9‘,使其“555”->“951”进而最大。只需要再扫一遍即可。
D - Snacktower
思路:div2A,水题。就是一直扫,碰见最大的就开始处理,具体处理是从大往下找,找打还未出现的最大的(因为你要等下一个最大的掉下来才能堆)
#include<bits/stdc++.h>
using namespace std;
const int N=100007;
int n,x,tmp;
bool exist[N];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
tmp=n;
for (int i=1;i<=n;i++)
{
cin>>x;
exist[x]=1;//标志数组
while (exist[tmp])//如果当前的存在
{
cout<<tmp<<" ";
tmp--;//一直往下循环找
}
cout<<endl;
}
}
E - Stripe
思路:就是个划分,前缀和处理
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[100005],sum;
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
a[i]=a[i]+a[i-1];
}
for(int i=2;i<=n;i++)
if (a[n]-a[i-1]==a[i-1])sum++;
cout<<sum<<endl;
}
F - Queue
待我多开一个博客好好写这个题
G - Mike and Feet
待我多开一个博客好好写这个题
H - Longest Regular Bracket Sequence
待我多开一个博客好好写这个题
I - Maximum Submatrix 2
待我...还是在这写了吧。
题意:给你一个n*m的01矩阵,求最大面积的'1'的矩阵(在列不动,行随意动的情况下)
思路:类似于前缀和预处理一下,但是不同的是我们a[i][j]表示的是a[i][j]往左有多个连续的1,如果断了那么从0开始(因为面积需要全部是1)。然后我们将每一列开始排序,比如{2,3,6,4,2,1,0,}取出来排序成{6,4,3,2,2,1,0},然后开始取max。
取max操作为b[i]*i(长乘以宽),不用取min的宽,因为当前的b[i]是降序排列。ans即可得出。
#include<bits/stdc++.h>
using namespace std;
const int N = 5000+7;
int n,m,a[N][N],b[N],ans,minn;
char c;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
cin>>c;
if (c=='1')
a[i][j]=a[i][j-1]+1;
else
a[i][j]=0;
}
for (int j=1;j<=m;j++)
{
for (int i=1;i<=n;i++)
b[i]=a[i][j];
sort(b+1,b+1+n,greater<int>());
for (int i=1;i<=n;i++)
if (b[i]==0) break;
else ans=max(ans,i*b[i]);
}
cout<<ans;
}
L - Cells Not Under Attack
思路:水题,直接看代码,好吧,统计列和行
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100007;
int h[N],l[N],x,y,tmp,n,m,xx,yy;
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
tmp=n*n;
xx=n;yy=n;
for (int i=1;i<=m;i++)
{
cin>>x>>y;
if (h[x]==0) h[x]=1,xx--;
if (l[y]==0) l[y]=1,yy--;
cout<<xx*yy<<" ";
}
}
S - Subsegments
是个div2的E,不错不错
思路:用map统计个数,设定一个set——s,用来表示当前区间内的数字,因为set是排序的,我们只需要输出*rbegin()就行(我用*end()就错了...)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+7;
int n,k,a[N];
map<int,int> mp;
set<int> s;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
for (int i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<k;i++)//预处理 其实也可以在下面的循环一起写 写个if
{
mp[ a[i] ]++;//个数+1
if (mp[ a[i] ]==1) s.insert(a[i]);//如果只有一个 s插入
else if (s.count(a[i])) s.erase(a[i]);//如果s中已经有 但是又出现了 删除
}
for (int i=k;i<=n;i++)
{
mp[ a[i] ]++;
if (mp[ a[i] ]==1) s.insert(a[i]);
else if (s.count(a[i])) s.erase(a[i]);//这三行同上预处理
mp[ a[i-k] ]--;//删除头
if (mp[ a[i-k] ]==1) s.insert(a[i-k]);//删除头
else if (mp[ a[i-k] ]== 0) s.erase(a[i-k]);
if (s.size()==0) cout<<"Nothing"<<endl;//set是空的 那么就输出nothing
else cout<<*s.rbegin()<<endl;//输出最后一个 set是排序的
}
}
V - Queries about less or equal elements
思路:水题...第一个秒的。给出a,b数组,问b数组每一个在a中有多少比他小的,sort一遍直接二分,b数组都不需要开
#include<bits/stdc++.h>
using namespace std;
const int N = 200007;
int n,m,a[N],x;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for (int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
for (int i=1;i<=m;i++)
{
cin>>x;
cout<<(upper_bound(a+1,a+1+n,x)-a)-1<<" ";
}
}
反思
有的时候感觉自己写不出,实际上真的写不出可能写的出,唉,多刷题多补题多总结吧,多写博客,这一次写下来,感觉以后还是分开写吧