CF370
废话
-
370:纪念盗笔青春
-
提交记录
几个脑残错误后文会提到
3.题目:
黄黄绿蓝蓝( 幸好 370 不是“红红红红红” | “黑黑黑黑黑” )
算法: 是没有滴 贪心,前缀和
正题
CF370A
签到数学题
车可以两步到达任意点 ,只需判断出发点与目标点是否在同行 | 同列
王有个性质是每次可以同时改变行列,但不必须,所以答案即为横纵坐标的差的最大值
象必须每次同时改变行列,并不能到达所有点 ( 白格只能到白格 )所以判断奇偶输出 0 ,剩下的点与车同理
#include <bits/stdc++.h>
using namespace std;
int x1,y1,x2,y2;
int main(){
cin>>x1>>y1>>x2>>y2;
if(x1==x2||y1==y2)cout<<1<<" ";
else cout<<2<<" ";
if(y1-x1==y2-x2||y1+x1==y2+x2)cout<<1<<" ";
else if((y1+x1)%2!=(y2+x2)%2)cout<<0<<" ";
else cout<<2<<" ";
cout<<max(abs(x2-x1),abs(y2-y1));
return 0;
}
CF370B
Berland Bingo
签到 不知道是什么 题
对每个卡暴力判断子集即可,因为若其他卡是他的子集,那么消他的时候那个卡也会被消掉
#include <bits/stdc++.h>
using namespace std;
const int N=105;
int n,m[N],a[N][N],o[N],maxn;
bool flag=1;
bool check(int x){
int cnt=0;
for(int i=1;i<=m[x];i++){
cnt+=o[a[x][i]];
}
if(cnt==m[x])return 0;
return 1;
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>m[i];
for(int j=1;j<=m[i];j++){
cin>>a[i][j];
maxn=max(maxn,a[i][j]);
}
}
for(int i=1;i<=n;i++){
flag=1;
for(int i=1;i<=maxn;i++)o[i]=0;
for(int j=1;j<=m[i];j++)o[a[i][j]]=1;
for(int j=1;j<=n;j++){
if(i==j||m[j]>m[i])continue;
if(!check(j)){
cout<<"NO"<<endl;
flag=0;
break;
}
}
if(flag)cout<<"YES"<<endl;
}
return 0;
}
CF370C
Mittens
题解全是错的,不要看
按照颜色数量排个序,发现左边换右边就行
发现若左边右边重合则同色
同色数量:2n-2o , o 为最大颜色数量
#include <bits/stdc++.h>
using namespace std;
const int N=5e3+3;
int n,m,a[N],p,cnt,o;
struct node{
int x,num;
}e[N];
bool cmp(node a,node b){
return a.x>b.x;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
if(a[i]!=a[i-1]){
e[++cnt].num=a[i-1],e[cnt].x=p;
o=max(o,p);
p=0;
}
p++;
}
if(p)e[++cnt].num=a[n],e[cnt].x=p;
o=max(p,o);
if(o>n/2)cout<<2*n-2*o<<endl;
else cout<<n<<endl;
sort(e+1,e+1+cnt,cmp);
n=0;
for(int i=1;i<=cnt;i++)
for(int j=1;j<=e[i].x;j++)a[n++]=e[i].num;
for(int i=0;i<n;i++){
cout<<a[i]<<" "<<a[(i+n/2)%n]<<endl;
}
return 0;
}
错误原因:if(p)e[++cnt].num=a[n],e[cnt].x=p;
没加最后一个块
CF370D
注意:方框==正方形
所以正方形的边长能确定,就是\(max(maxx-minx,maxy-miny)\)
然后就直接枚举正方形的左上角判断是否所有 \(w\) 都在框上
如何判断是否所有 \(w\) 都在框上?
用二维前缀和!大正方形 - 比他小一圈的正方形 = 框
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=2005;
int n,m,sum[N][N],minx=0x7f7f7f7f,miny=0x7f7f7f7f,maxx,maxy,edge,num;
char a[N][N];
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+(a[i][j]=='w');
if(a[i][j]=='w')num++,minx=min(minx,i),maxx=max(maxx,i),miny=min(miny,j),maxy=max(maxy,j);
}
}
edge=max(maxx-minx,maxy-miny)+1;
if(edge>min(n,m)){cout<<-1;return 0;}
// cout<<num;
for(int i=1;i+edge-1<=n;i++){
for(int j=1;j+edge-1<=m;j++){
int x1=i,y1=j,x2=i+edge-1,y2=j+edge-1,a1=x1+1,a2=x2-1,b1=y1+1,b2=y2-1;
//if(i==1&&j==3)cout<<x1<<" "<<x2<<" "<<y1<<" "<<y2;
if(edge>2){
if(sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]==num){
if(!(sum[a2][b2]-sum[a2][b1-1]-sum[a1-1][b2]+sum[a1-1][b1-1])){
for(int k=1;k<=n;k++){
for(int h=1;h<=m;h++){
if(((k==x1&&(h<=y2&&h>=y1))||(k==x2&&(h<=y2&&h>=y1)))||((h==y1&&(k<=x2&&k>=x1))||(h==y2&&(k<=x2&&k>=x1))))
{
if(a[k][h]=='w')cout<<'w';
else cout<<'+';
}else cout<<'.';
}
cout<<endl;
}
// for(int k=1;k<=n;k++){
// for(int h=1;h<=m;h++){
// if(a)
// }
// cout<<endl;
// }
return 0;
}
}
}else {
if(sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1]==num){
for(int k=1;k<=n;k++){
for(int h=1;h<=m;h++){
if(((k==x1&&(h<=y2&&h>=y1))||(k==x2&&(h<=y2&&h>=y1)))||((h==y1&&(k<=x2&&k>=x1))||(h==y2&&(k<=x2&&k>=x1))))
{
if(a[k][h]=='w')cout<<'w';
else cout<<'+';
}else cout<<'.';
}
cout<<endl;
}
return 0;
}
}
}
}
cout<<-1<<endl;
return 0;
}
由提交记录得我挂了多次, 还好有拍子
错误:
- a[k][h] 写成 a[h][k]
- maxy=max(maxy,j) 写成 maxy=min(maxy,j)
- ! 不打 ()
我还是太菜了
CF370E
cf 上的题解是 dp ,但我看不懂 ,洛谷的题解也像()一样,连代码都没有 ,故这里只讲我的贪心 ,( 有大佬会 dp 浇浇 )
记录一个 pair 的 minn maxn 表示使结果最小/最大的当前的数和量
于是可以由上一个转移过来
if(maxn[i-1].se>=2)maxn[i]=pii(maxn[i-1].fi+1,1);
else maxn[i]=pii(maxn[i-1].fi,maxn[i-1].se+1);
if(minn[i-1].se==5)minn[i]=pii(minn[i-1].fi+1,1);
else minn[i]=pii(minn[i-1].fi,minn[i-1].se+1);
目的就是判断可不可行 if(minn[i].fi>a[i]||maxn[i].fi<a[i])
到规定值时要手动修改值
maxn[i]=min(maxn[i],pii(a[i],5)); minn[i]=max(minn[i],pii(a[i],1));
手动修改值后
输出 直接取 maxn 即可
其实看代码更好理解
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
#define pii pair<int,int>
#define fi first
#define se second
pii minn[N],maxn[N];
int n,a[N],cnt[N];
int main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
if(a[1]>1){
cout<<-1;
return 0;
}
minn[1]=maxn[1]=pii(1,1);
for(int i=2;i<=n;i++){
if(maxn[i-1].se>=2)maxn[i]=pii(maxn[i-1].fi+1,1);
else maxn[i]=pii(maxn[i-1].fi,maxn[i-1].se+1);
if(minn[i-1].se==5)minn[i]=pii(minn[i-1].fi+1,1);
else minn[i]=pii(minn[i-1].fi,minn[i-1].se+1);
if(a[i]){
if(minn[i].fi>a[i]||maxn[i].fi<a[i]){
// cout<<i;
cout<<-1;
return 0;
}
maxn[i]=min(maxn[i],pii(a[i],5));
minn[i]=max(minn[i],pii(a[i],1));
}
// cout<<maxn[i].fi<<" "<<maxn[i].se<<" "<<minn[i].fi<<" "<<minn[i].se<<endl;
}
if(maxn[n].se==1)maxn[n]=pii(maxn[n].fi-1,5);
if(maxn[n]<minn[n]){
cout<<-1<<endl;
return 0;
}
cout<<maxn[n].fi<<endl;
a[n]=maxn[n].fi;
cnt[a[n]]=1;
for(int i=n-1;i;i--){
a[i]=min(maxn[i].fi,a[i+1]);
if(cnt[a[i]]==5) a[i]--;//手动修改
cnt[a[i]]++;
}
for(int i=1;i<=n;i++)cout<<a[i]<<' ';
return 0;
}