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;
}