在这里写下每题的答案吧
1.纸牌均分问题的贪心
由于最左边只能由其右边填补,所以考虑从左边开始遍历,遇到不等于平均值的就从右边补就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1005;
int n;
int a[N];
int main() {
cin>>n;
ll sum=0;
for(int i=1;i<=n;i++) {
cin>>a[i];
sum+=a[i];
}
ll k=sum/n;
int ans=0;
for(int i=1;i<=n;i++) {
if (a[i]<k) {
a[i+1]-=(k-a[i]);
a[i]=k;
ans++;
}
if (a[i]>k) {
a[i+1]+=(a[i]-k);
a[i]=k;
ans++;
}
}
cout<<ans;
return 0;
}时间复杂度O(n)
2.这题直接dfs就好了,设置一个vis数组记录哪些点被遍历过了,如果遇到vis[x]==0的情况,把其子树中vis[x]==0的点全置1就好了。
代码:
#include<bits/stdc++.h>
#define pb push_back
#define SZ(x) (int)x.size()
using namespace std;
const int N=100005;
int n,x,q,num;
int vis[N];
vector<int> g[N];
void dfs(int x) {
int len=SZ(g[x]);
for(int i=0;i<len;i++) {
int v=g[x][i];
if (!vis[v]) {
num++;
vis[v]=1;
dfs(v);
}
}
}
int main() {
cin>>n;
for(int i=1;i<n;i++) {
cin>>x;
g[x].pb(i);
}
cin>>q;
int sum=n;
while(q--) {
scanf("%d",&x);
if (!vis[x]) {
num=1;
vis[x]=1;
dfs(x);
sum-=num;
printf("%d\n",sum);
}
else {
printf("%d\n",sum);
}
}
return 0;
}时间复杂度O(n)
3.按照x.dy.c<y.cx.d排序,如果相等的话,id小的在前面。
代码:
#include<bits/stdc++.h>
#define FULL(x,y) memset(x,y,sizeof(x))
#define ll long long
#define SZ(x) (int)x.size()
#define pb push_back
using namespace std;
const int N=1005;
struct node {
int c,d,id;
}no[N];
bool cmp(const node& x, const node& y) {
if (x.d*y.c==y.d*x.c) return x.id < y.id;
return x.d*y.c < y.d*x.c;
}
int n;
int main() {
cin>>n;
for(int i=1;i<=n;i++) {
cin>>no[i].d>>no[i].c;
no[i].id=i;
}
sort(no+1,no+1+n,cmp);
for(int i=1;i<=n;i++) {
cout<<no[i].id<<' ';
}
return 0;
}时间复杂度O(nlogn)。
4.这题应该dp,令dp[i][j]表示以i为结尾且与前面的数相乘%2021==j的最长长度,则有状态转移方程:
dp[i][(a[i]*a[j])%2021]=max(dp[i][(a[i]*a[j])%2021], dp[j][a[i]]+1),当dp[j][a[i]]!=0。且还需维护总数,令开一个cnt[i][j]数组维护。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n;
int a[N],dp[N][2021],cnt[N][2021],f[N][2021];
int main() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
//初始化
for(int i=1;i<=n;i++) {
for(int j=i-1;j>=1;j--) {
dp[i][(a[i]*a[j])%2021]=2;
f[i][(a[i]*a[j])%2021]++;
}
}
//dp
for(int i=3;i<=n;i++) {
for(int j=i-1;j>=2;j--) {
if (dp[j][a[i]]) {
dp[i][(a[i]*a[j])%2021]=max(dp[i][(a[i]*a[j])%2021],dp[j][a[i]]+1);
}
}
//维护数量
for(int j=i-1;j>=2;j--) {
if (dp[i][(a[i]*a[j])%2021]==dp[j][a[i]]+1) {
if (dp[j][a[i]]==2)cnt[i][(a[i]*a[j])%2021]+=f[j][a[i]];
else cnt[i][(a[i]*a[j])%2021]+=cnt[j][a[i]];
}
}
}
int ans=0,sum=0;
for(int i=1;i<=n;i++) {
for(int j=0;j<2021;j++) {
if (dp[i][j]>=3) ans=max(ans,dp[i][j]);
}
}
for(int i=1;i<=n;i++) {
for(int j=0;j<2021;j++) {
if (dp[i][j]==ans) sum+=cnt[i][j];
}
}
if (ans!=0)cout<<sum<<endl<<ans<<endl;
else cout<<0<<endl<<0<<endl;
return 0;
}时间复杂度O(n^2)。

京公网安备 11010502036488号