A题
并查集或者最小生成树
//并查集
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e+5;
int f[maxn];
struct node
{
int x;int y;int w;
}e[maxn];
bool cmp(node a,node b)
{
return a.w<b.w;
}
void init(int n)
{
for(int i=1;i<=n;i++)
{
f[i]=i;
}
}
int find(int x)
{
if(f[x]==x)
return x;
else
return f[x]=find(f[x]);
}
int main()
{
int n,m;
cin>>n>>m;
int x,y,z;
init(n);
for(int i=1;i<=m;i++)
{
cin>>x>>y>>z;
e[i].x=x;
e[i].y=y;
e[i].w=z;
}
sort(e+1,e+m+1,cmp);
int cnt1=0,cnt2=0;
for(int i=1;i<=m;i++)
{
int rx=find(e[i].x);
int ry=find(e[i].y);
if(rx!=ry)
{
cnt1++;
f[rx]=ry;
if(e[i].w==1)
{
cnt2++;
}
if(cnt1==n-1)
{
break;
}
}
}
if(cnt1==n-1)
cout<<cnt2;
else
cout<<-1;
}
B题
线段树
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
struct node
{
int l,r;
int maxx,cnt;
}t[maxn<<2];
int w[maxn];
void pushup(int rt)
{
if(t[rt<<1].maxx==t[rt<<1|1].maxx)
{
t[rt].maxx=t[rt<<1].maxx;
t[rt].cnt=t[rt<<1].cnt+t[rt<<1|1].cnt;
}
else
{
if(t[rt<<1].maxx>t[rt<<1|1].maxx)
{
t[rt].maxx=t[rt<<1].maxx;
t[rt].cnt=t[rt<<1].cnt;
}
else
{
t[rt].maxx=t[rt<<1|1].maxx;
t[rt].cnt=t[rt<<1|1].cnt;
}
}
}
void build(int u,int l,int r)
{
t[u].l=l,t[u].r=r;
if(l==r)
{
t[u].cnt=1;
t[u].maxx=w[l];
return ;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
void updata(int x,int y,int z)
{
if(t[x].l==t[x].r)
{
t[x].maxx=y;
return ;
}
int mid=(t[x].l+t[x].r)>>1;
if(z<=mid)
updata(x<<1,y,z);
else
updata(x<<1|1,y,z);
pushup(x);
}
node query(int x,int l,int r)
{
if(t[x].l>=l&&t[x].r<=r)
{
return {l,r,t[x].maxx,t[x].cnt};
}
node res={l,r,-1,0};
int mid=(t[x].l+t[x].r)>>1;
if(l<=mid)
{
res=query(x<<1,l,r);
}
if(r>mid)
{
node p=query(x<<1|1,l,r);
if(res.maxx==p.maxx)
res.cnt+=p.cnt;
else if(res.maxx<p.maxx)
{
res=p;
}
}
return res;
}
int n,m;
char s[10];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
build(1,1,n);
while(m--)
{
scanf("%s",s);
int x,y;
scanf("%d%d",&x,&y);
if(s[0]=='A')
{
node ans=query(1,x,y);
cout<<ans.maxx<<" "<<ans.cnt<<endl;
}
else
{
updata(1,y,x);
}
}
}
C题
模拟水题
#include<iostream>
#include<math.h>
using namespace std;
typedef long long ll;
int main()
{
ll n;
cin>>n;
ll cnt=0;
cnt=n/4;
ll sum=cnt*2;
ll m;
m=n-sum*2;
if(m==3)
{
cout<<sum+1<<endl;
return 0;
}
ll res=m+sum;
cout<<res<<endl;
}
D题
素数筛
题目的大意就是找最大公约数,素数之间没有最大公约数
所以找到最多可能的素数然后再加上一个非素数就有了最大公约数
所以最后答案就是素数个数+1
//欧拉素数筛
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=1e5+5;
int pri[maxn];
int pd[maxn];
void Pri()
{
int t;//记数
memset(pri,0,sizeof(pri));
memset(pd,0,sizeof(pd));
pd[0]=pd[1]=0;
for(int i=2;i<=maxn;i++)
{
if(!pd[i])
pri[++t]=i;
for(int j=1;j<=t&&i*pri[j]<=maxn;j++)
{
pd[i*pri[j]]=1;
if(i*pri[j]==0)
break;
}
}
}
int main()
{
int n;
int sum;
Pri();
cin>>n;
if(n<=3)
cout<<-1;
else
{
for(int i=1;i<=n;i++)
if(pd[i]==0)
sum++;
cout<<sum+1<<endl;
}
}
E题
字符串模拟相加的弱化版,没有进位,注意一下为0时候特殊判断一下就行
#include<iostream>
#include<string>
using namespace std;
string addStrings(string num1, string num2)
{
int a1 = num1.size() - 1;
int a2 = num2.size() - 1;
string ret; //相加后的字符串保存在 ret 里面
int sum = 0; //两字符串对应位 相加之后的和
while (a1 >= 0 || a2 >= 0)
{
sum = 0;
if (a1 >= 0)
{
sum += num1[a1] - '0'; // 将字符数字转化为 数字 再相加 ‘5’----->5
}
if (a2 >= 0)
{
sum += num2[a2] - '0';
}
if (sum >= 10) //对应位相加 再加上进位 如果大于>=10说明要进位 更新step为1
{
sum -= 10; //sum-10的值 是相加后当前位的值
}
else
{
//step = 0; //如果没有进位step要更新为0
}
ret.insert(0, 1, sum + '0');
a1--;
a2--;
}
return ret;
}
int main()
{
string s1;
string s2;
string z;
cin >> s1 >> s2;
z=addStrings(s1, s2);
int n=z.length();
int flag=0;
for(int i=0;i<n;i++)
{
if(z[i]!='0')
{
cout<<z[i];
flag=1;
}
else if(flag==1)
{
cout<<z[i];
}
}
if(flag==0)
cout<<0;
return 0;
}
F题
贪心,一直选最大的那个就行,剩下最后一个不拿;
所以答案就是,全体的和+最大的数*(n-2);
//贪心
#include<iostream>
#include<math.h>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int main()
{
ll n,a[maxn];
ll maxx=0;
ll sum=0,res=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
maxx=max(maxx,a[i]);
sum+=a[i];
}
res=sum+maxx*(n-2);
cout<<res<<endl;
}
G题
模拟
先排序然后比较
没有找到比他大的就往下找
找到的话就两个一起向下
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=2e5+5;
int main()
{
int n,m;
int a[maxn],b[maxn];
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=m;i++)
{
cin>>b[i];
}
sort(a+1,a+n+1);
sort(b+1,b+1+m);
int s1=1,s2=1;
int cnt=0;
while(s1<=n&&s2<=m)
{
if(a[s1]>b[s2])
{
cnt++;
s1++;
s2++;
}
else
{
s1++;
}
}
cout<<cnt<<endl;
}
H题
优先队列的用法,默认大根堆,降序排列
//优先队列
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=2e5+5;
int a[maxn];
priority_queue<int> q;
int main()
{
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
sort(a+1,a+1+n);
for(int i=1;i<=min(k,n);i++)
{
q.push(a[i]);
}
int c,s;
for(int i=1;i<=m;i++)
{
cin>>c;
if(c==2)
{
if(q.size()<k)
{
cout<<-1<<endl;
continue;
}
s=q.top();
cout<<s<<endl;
}
else
{
int s;
cin>>s;
if(q.size()<k)
{
q.push(s);
continue;
}
if(q.top()>s)
{
q.pop();
q.push(s);
}
}
}
}
I题
J题
dp,从第一个开始向右遍历 dp[i][1]是选第i个,dp[i][0]是不选
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll a[maxn],cnt[maxn],dp[maxn][2];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
cnt[a[i]]+=a[i]; //题目中说有相同的可以一直拿
}
dp[1][1]=cnt[1];
ll maxx=dp[1][1];
for(int i=2;i<maxn;i++) //用桶排序
{
dp[i][1]=max(dp[i-1][1],dp[i-1][0]+cnt[i]);//选dp[i-1][1]的话就不能选dp[i];
dp[i][0]=max(dp[i-1][0],dp[i-1][1]); //dp[i][0]不选,就判断dp[i-1]选和不选的情况
maxx=max(maxx,dp[i][0]);
maxx=max(maxx,dp[i][1]);
}
cout<<maxx<<endl;
}