目录
#65
AcWing 4603. 最大价值
#include <bits/stdc++.h>
#define all(v) (v).begin(),(v).end()
#define rep(i,x,n) for(int i=x;i<=n;i++)
#define INF 0x3f3f3f3f
#define DINF 0xc0c0c0c0
//#define x first
#define y second
#define PII pair<int,int>
#define pb push_back
//#define int long long
using namespace std;
const int N=110;
void solve()
{
int n,ans=0;
string s;
cin>>n>>s;
rep(i,0,n-1)
if(s[i]=='A')
{
int j=i+1,cnt=0;
while(s[j]=='P'&&j<n) cnt++,j++;
ans=max(ans,cnt);
i=j-1;//跳过这些已计算的P -1是因为循环的i还要+1 实际位置是下一个A
}
cout<<ans<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
AcWing 4604. 集合询问
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1<<18;
int cnt[N],x;
int get(int x)
{
int t=0,ans=0;
while(x) //把x转化为对应的模板s
{
ans+=(x&1)<<t++;
x/=10;
}
return ans;
}
void solve()
{
string op;
cin>>op>>x;
if(op[0]=='+') cnt[get(x)]++;
else if(op[0]=='-') cnt[get(x)]--;
else cout<<cnt[get(x)]<<endl;
}
signed main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
AcWing 4605. 最大周长
#include <iostream>
using namespace std;
const int N=3e5+10, INF = 1e9;
int n;
int x[N],y[N];
int main()
{
cin>>n;
int u=-INF,d=INF,l=INF,r=-INF;
for(int i=0;i<n;i++)
{
cin>>x[i]>>y[i];
u=max(u,y[i]),d=min(d,y[i]);
l=min(l,x[i]),r=max(r,x[i]);
}
int res=0;
//列举三个点时
for(int i=0;i<n;i++)
res=max(res,max(u-y[i],y[i]-d) + max(r-x[i],x[i]-l)); //如果是三个点 必有一点在矩形顶点
cout<<res*2<<' ';
//列举四个点时输出f(4) f(5) …… f(n)
for(int i=4;i<=n;i++) cout<<2*(u-d+r-l)<<' ';
return 0;
}
#66
AcWing 4607. 字母补全
wa16 淦
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int main()
{
char ch[26]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
int ck[26]={0};
bool f=false;
int t=0,cnt=0,p=0;
string a;
cin>>a;
if(a.size()<26) f=true;
for(int i=0;i<a.size();i++)
{
if(a[i]!='?') ck[a[i]-'A']++;
else p++;
}
for(int j=t;j<26;j++) if(ck[j]==0) cnt++;
if(p<cnt) f=true;
if(f) cout<<-1;
else
{
for(int i=0;i<a.size();i++)
if(a[i]!='?') cout<<a[i];
else if(a[i]=='?'&&cnt!=0)
{
for(int j=t;j<26;j++)
if(!ck[ch[j]-'A'])
{
t=j;
cout<<ch[j];
ck[ch[j]-'A']++;
cnt--;
break;
}
}else if(a[i]=='?'&&cnt==0) cout<<'A';
}
return 0;
}
#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_set>
#include<vector>
using namespace std;
int main()
{
string s;
cin>>s;
unordered_set<char>hash;//存字符串中的字母
vector<char>cs;//存序列中未出现的元素
for(int i=25;i<s.size();i++)
{
hash.clear();
bool flag=true;//判断连续的字符串中是否有重复的元素,如果有则弄为false
//则该序列不符合
//枚举区间长度为26的连续字符串
for(int j=i-25;j<=i;j++)
{
if(s[j]!='?'&&hash.count(s[j]))
{
flag=false;
break;
}
else hash.insert(s[j]);//否则不出现重复元素则存入哈希表中
}
if(flag)
{
cs.clear();
for(char c='A';c<='Z';c++)
{
//如果该元素在这段序列中不存在,则存入cs中 用来填问号中的元素
if(!hash.count(c)) cs.push_back(c);
}
for(int j=i-25,k=0;j<=i;j++)
{
//填充问号部分
if(s[j]=='?') s[j]=cs[k++];
}
//如果未出现的元素都已经填充完了,那就填A。
for(auto&c:s)
{
if(c=='?') c='A';
}
cout<<s<<endl;
return 0;
}
}
puts("-1");
}
AcWing 4608. 整数分组
题意:
在数组中只出现一次的数字叫超级数
现在要求划分两个数组 A B 使两数组的超级数个数相等
思路:
统计超级数的个数cnt 分情况讨论:
- cnt是偶数。只要平均分配就好了,非超级数的直接放B集合,因为它对结果不产生影响
- cnt是奇数。如果数组中存在一个出现次数大于2的数,抽1个出来凑cnt为偶数的情况
比如:1 1 1 2 3 5 6 6 可以分为 1 2 3 5 1 1 6 6
因为题目是spj 所以只要抽出数组中出现的第一次大于2的数拿来用就可以
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N=110;
string s;
int main()
{
int n,a[N],cnt=0;
bool f=false;
map<int,int>mp;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++)
mp[a[i]]++;
for(auto x:mp) if(x.y==1) cnt++;
if(cnt%2==0)
{
int t=cnt/2;
for(int i=1;i<=n;i++)
if(mp[a[i]]==1&&t) s+='A',t--;
else s+='B';
cout<<"YES"<<endl;
cout<<s<<endl;
return 0;
}
else
{
for(auto x:mp)
if(x.y>2)
{
int t=cnt/2;
f=true;
int flag=1; //flag用于控制配问题 抽1个该数凑超级数相等
for(int i=1;i<=n;i++)
if(a[i]==x.x) //找出第一个出现次数大于2的数
if(flag) flag--,s+='A';
else s+='B';
else
{
if(mp[a[i]]==1&&t) s+='A',t--;
else s+='B';
}
cout<<"YES"<<endl;
cout<<s<<endl;
return 0;
}
}
cout<<"NO"<<endl;
return 0;
}
#67
AcWing 4609. 火柴棍数字
#include <iostream>
using namespace std;
void solve()
{
int n;
cin>>n;
if(n%2) cout<<7;
else cout<<1;
for(int i=1;i<=n/2-1;i++) cout<<1;
cout<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
return 0;
}
AcWing 4610. 列表排序
题意:
允许对每一行最多进行一次操作,并选择任意两列最多交换一次,共 n + 1 次操作。
思路:
如果每行里有两个数与原排序不同 则通过一次交换即可完成
比如1 2 4 3 与原序列1 2 3 4 有两处不同
#include <iostream>
using namespace std;
const int N = 22;
int n, m;
int g[N][N];
bool check()
{
for(int i=1;i<=n;i++) //因为如果只交换该行的两个数字的话 cnt=2
{
int cnt = 0;
for (int j=1;j<=m;j++)
if(g[i][j]!=j)
cnt++;
if(cnt>2) return false;
}
return true;
}
int main()
{
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<=m;i++)
for(int j=i;j<=m;j++)//j=i时相当于不交换 等价于只进行第一步操作
{
for(int k=1;k<=n;k++) swap(g[k][i], g[k][j]);//交换两列 第二步操作
if (check())//check检测整个列表是否符合要求
{
puts("YES");
return 0;
}
for(int k=1;k<=n;k++) swap(g[k][i], g[k][j]);
}
puts("NO");
return 0;
}
AcWing 4611. 串联数字
题意:
思路:
#70
AcWing 4618. 两个素数
#include <iostream>
using namespace std;
bool isprime(int x)
{
if(x<2) return false;
for(int i=2;i<=x/i;i++)
if(x%i==0) return false;
return true;
}
int main()
{
int n;
cin>>n;
if(isprime(n))
{
cout<<1<<' '<<n;
return 0;
}
for(int i=2;i<=n/i;i++)
if(n%i==0)
{
if(n/i==i) cout<<i<<' '<<i; //如果是平方数 如4 输出2 2
else cout<<i<<' ';
while(n%i==0) n/=i;
}
if(n>1) cout<<n;
}
#include<bits/stdc++.h>
using namespace std;
int n;
bool is_prime(int x)
{
if(x < 2) return false;
for(int i=2;i<=x/i;i++)
if(x%i==0)
return false;
return true;
}
int main()
{
cin>>n;
for(int i=2;i<=n;i++)
{
if(n%i) continue;
if(is_prime(i)&&is_prime(n/i))
{
cout<<i<<" "<<n/i<<endl;
return 0;
}
}
return 0;
}
AcWing 4619. 减法操作
#73
AcWing 4704. 数对 - ac
思路:
枚举每个元素和后面的元素比较看是否符合条件 如果符合cnt+=2
因为(1,2)和(2,1)是不同的
import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(),d=sc.nextInt();
int[] a=new int[n];
int cnt=0;
for(int i=0;i<n;i++) a[i]=sc.nextInt();
for(int i=0;i<n-1;i++)
for(int j=i+1;j<n;j++)
if(Math.abs(a[i]-a[j])<=d) cnt+=2;
System.out.print(cnt);
}
}
AcWing 4705. 矩阵
思路:
把它旋转的四种情况都存进数组 通过排序 把最小的情况放入set去重
只要是相同的矩阵 则他们的最小情况都是一样的
a b c a d c b d c d d b b a a c
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
Set<Integer> st=new HashSet<>();
for(int i=0;i<n;i++)
{
if(i>0) sc.next(); //吞掉**
String s=sc.next();
int a=s.charAt(0)-'0',b=s.charAt(1)-'0';
s=sc.next();
int c=s.charAt(0)-'0',d=s.charAt(1)-'0';
int[] arr=new int[4];
//这里是按矩阵转的顺序
arr[0]=a*1000+b*100+c*10+d;
arr[1]=b*1000+d*100+a*10+c;
arr[2]=c*1000+a*100+d*10+b;
arr[3]=d*1000+c*100+b*10+a;
Arrays.sort(arr);
st.add(arr[0]);
}
System.out.print(st.size());
}
}
AcWing 4706. 最短路程
思路:
import java.util.*;
public class Main {
static int N=100010,M=N*2,n,idx;
static int[] e=new int[M],ne=new int[M],w=new int[M],h=new int[N];
static void add(int a,int b,int c)
{
e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;
}
static int dfs(int u, int fa)
{
int ans=0;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(j==fa) continue;//由于是无向图 走到底的标志是该点的下一个节点等于其父节点
ans=Math.max(ans,w[i]+dfs(j,u));//这个点的到底的最大长度=它下一个点的dfs+这条边的长度
}
return ans;
}
public static void main(String[] args)
{
Arrays.fill(h, -1);
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
long res=0;
for(int i=0;i<n-1;i++)
{
int a=sc.nextInt(),b=sc.nextInt(),c=sc.nextInt();
add(a, b, c);
add(b, a, c);
res+=c*2;
}
System.out.println(res-dfs(1,-1));
}
}
#76
AcWing 4714. 数对 - ac
无语啦 卡在c++语法上呜呜呜
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int main()
{
string s;
cin>>s;
unordered_map<char,ll> mp;
ll sum=0;
for(auto x:s) mp[x]++;
for(auto x:mp) sum+=x.second*x.second;
cout<<sum<<endl;
}