2022/5/7

142 篇文章 0 订阅
142 篇文章 1 订阅

Equalize the Array

我们每个数出现了多少次统计出来,cnt数组记录了cnt[i]表示有几个数出现了i次,sum是记录了出现次数小于等于i次的一共有多少数,ct记录了出现次数小于等于i次的一共有多少不同的数,这样对于一个i来说,我们保留出现i次的数,那么少于i次的我们要全部删除,多于i次的我们要删除多余的那部分,即

sum[i-1]+(sum[n]-sum[i]-(ct[n]-ct[i])*i);

这样就可以进行O(n)的遍历了;

#include<bits/stdc++.h>
#define ll long long
#define lowbit(i) ((-i)&(i))
using namespace std;
const ll inf=1e18;
const ll mod=998244353;
ll t,n,a[200005],cnt[200005],sum[200005],ct[200005];
map<ll,ll>mp;
int main(){
	//freopen("in.txt","r",stdin);
	scanf("%lld",&t);
	while(t--){
        mp.clear();
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);cnt[i]=0;ct[i]=0;
            mp[a[i]]++;
        }
        for(int i=1;i<=n;i++){
            if(mp[a[i]]) cnt[mp[a[i]]]++;
            mp[a[i]]=0;
        }
        for(int i=1;i<=n;i++) sum[i]=sum[i-1]+cnt[i]*i,ct[i]=ct[i-1]+cnt[i];;
        ll ans=inf;
        for(int i=1;i<=n;i++){
            ll x=sum[i-1]+(sum[n]-sum[i]-(ct[n]-ct[i])*i);
            ans=min(ans,x);
        }
        printf("%lld\n",ans);
	}
	return 0;
}

LCM Challenge

如果n是奇数的话,n为奇数,(n-1) 为偶数,(n-2)为奇数,两两互质所以n*(n-1)*(n-2)是最大的;若n是偶数的话,n和n-2都是偶数,那就退一步选n-3,但n-3可能与n不互质,当n为3的倍数时n与n-3就是不互质的,所以再退一步选择(n-1)*(n-2)*(n-3),当n不为3的倍数时就可以选择n*(n-1)*(n-3)了;

(8条消息) LCM Challenge(暴力)_404-unkown的博客-CSDN博客

#include<bits/stdc++.h>
#define ll long long
#define lowbit(i) ((-i)&(i))
using namespace std;
const ll inf=1e18;
const ll mod=998244353;
ll n;
int main(){
	//freopen("in.txt","r",stdin);
	scanf("%lld",&n);
	if(n<3){
        printf("%lld\n",n);
        return 0;
	}
	ll ans=0;
	if(n&1) ans=n*(n-1)*(n-2);//n为奇数时
	else if(n%2==0&&n%3!=0) ans=n*(n-1)*(n-3);//n为偶数且n为3的倍数时
	else if(n%2==0&&n%3==0) ans=(n-1)*(n-2)*(n-3);//n为偶数且n不为3的倍数时
	printf("%lld\n",ans);
	return 0;
}

树 - 题目 - Daimayuan Online Judge

一开始题目看错了,一直没弄懂样例是咋回事,然后就去看大佬的题解看懂题意,但无奈一不小心瞥到了思路,,,背包;只要看出每个点的出度就是容量,价值是1,然后去做01背包就可以了;

#include<bits/stdc++.h>
#define ll long long
#define lowbit(i) ((-i)&(i))
using namespace std;
const ll inf=1e18;
const ll mod=998244353;
ll n,a[3005],dp[3005],m;
int main(){
	//freopen("in.txt","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<n;i++){
        ll x;
        scanf("%lld",&x);
        a[x]++;
	}
	m=0;
	for(int i=1;i<=n;i++) {dp[i]=inf;if(a[i]) m++;}
	dp[1]=0;dp[0]=inf;
	for(int i=1;i<=n;i++)
        for(int j=n;j>=a[i];j--){
            dp[j]=min(dp[j],dp[j-a[i]]+1);
            //if(j==6) cout<<dp[j]<<" "<<dp[j-a[i]]<<endl;
        }
    for(int i=1;i<=n;i++){
        printf("%lld ",dp[i]==inf?-1:dp[i]);
    }
	return 0;
}

P6278 [USACO20OPEN]Haircut G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这次是自己想的思路,和之前的好像差不多,这次我想的是先求出一开始数组的总逆序对个数来,期间记录每个数作为较小值所产生的逆序对个数,我们的j是逐次减1的,那么如果j减到了x,那么比x大的数都变为了x,原先为x的数所产生的那些逆序对中较大值大于x的就都删除了,其实也就是x作为较小值所产生的逆序对就都没了,这个值我们上面记录了,所以可以直接减去,这样就得到了j=x时的答案,其他的也一样;

#include<bits/stdc++.h>
#define ll long long
#define lowbit(i) ((-i)&(i))
using namespace std;
const ll inf=1e18;
const ll mod=998244353;
ll n,ans[100005],t[100005],tx[100005];
struct node{
    ll id,v;
    bool operator<(const node &a)const{
        if(a.v==v) return id>a.id;
        return v>a.v;
    }
}a[100005];
void add(ll x){
    for(int i=x;i<=n;i+=lowbit(i))
        t[i]++;
}
ll ask(ll x){
    ll res=0;
    for(int i=x;i;i-=lowbit(i))
        res+=t[i];
    return res;
}
int main(){
	//freopen("in.txt","r",stdin);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i].v),a[i].id=i;
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
        ans[n]+=ask(a[i].id-1);
        tx[a[i].v]+=ask(a[i].id-1);
        add(a[i].id);
    }
    for(int i=n-1;i>=0;i--){
        ans[i]=ans[i+1]-tx[i];
        //cout<<tx[i]<<" "<<i<<endl;
    }
    for(int i=0;i<=n-1;i++) printf("%lld\n",ans[i]);
	return 0;
}

E-禅_牛客小白月赛49 (nowcoder.com)

假设dp[i]为从第i个位置向公主走需要的最小的m,可以手模一下 2 2 2 1 10 0和2 2 2 2 1 10 0这两组样例,发现有个式子:dp[i]=dp[i+1]-a[i],然后在第二个数据的第一个2也就是dp[1]会发现不能等于2,最小也得是3,也就是转移的式子要这样写:dp[i]=max(dp[i+1]-a[i],a[i]+1),0右边的也是这样推,这个题就结束了,还需要注意的是不要忘记n=1的时候特判;

【比赛题目讲解】牛客小白月赛49(fried-chicken)_哔哩哔哩_bilibili

#include<bits/stdc++.h>
#define ll long long
#define lowbit(i) ((-i)&(i))
using namespace std;
const ll inf=1e18;
const ll mod=998244353;
ll t,n,a[100005],dp[100005];
int main(){
	//freopen("in.txt","r",stdin);
    scanf("%lld",&t);
    while(t--){
        scanf("%lld",&n);
        ll ma=0,ans=inf;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            if(a[i]==0) ma=i;
        }
        if(n==1){printf("No Solution\n");continue;}
        if(ma>1) dp[ma-1]=a[ma-1]+1,ans=min(ans,dp[ma-1]);
        if(ma<n) dp[ma+1]=a[ma+1]+1,ans=min(ans,dp[ma+1]);
        //cout<<dp[ma+1]<<" "<<ma+1<<" "<<ans<<endl;
        for(int i=ma-2;i>=1;i--)
            dp[i]=max(dp[i+1]-a[i],a[i]+1),ans=min(ans,dp[i]);
        for(int i=ma+2;i<=n;i++)
            dp[i]=max(dp[i-1]-a[i],a[i]+1),ans=min(ans,dp[i]);
        printf("%lld\n",ans);
    }
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

killer_queen4804

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值