codeforces-1353-A. Most Unstable Array
题意:给你两个数n,m,让你构造一个长度为n个数列a,使得数列中每个数的和为m,且让 最大,并输出
如果n>2 最大就是ans=2*m 构造是序列是 0,m,0,0,……,但是如果n==2,就是0,m,ans=m,分类讨论
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a)&-(a))
#define clean(a,b) memset(a,b,sizeof(a))
const int mod = 1e9 + 7;
const int inf=0x3f3f3f3f;
const int maxn = 2e5+9;
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
int _;
//==================================================================
//==================================================================
int main()
{
for(scanf("%d",&_);_;_--)
{
int n,m;
scanf("%d%d",&n,&m);
if(n==1) printf("0
");
else if(n==2) printf("%d
",m);
else printf("%d
",m*2);
}
return 0;
}
codeforces-1353-B. Two Arrays And Swaps
题意:给你两个数组a,b,均由正数组成,再给你一个整数k,你有k次机会把a,b数组里的某一对数交换一下,问交换之后a数组的和的最大值
因为有k次机会交换,那就是有k次机会用b数组里大的数替代a里比较小的,分别对两数组从小到大排序,前k个从b的后面往前面取,如果a[i]>=b[n-i+1] break;后面加上a数组剩下的 就可以了
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a)&-(a))
#define clean(a,b) memset(a,b,sizeof(a))
const int mod = 1e9 + 7;
const int inf=0x3f3f3f3f;
const int maxn = 2e5+9;
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
int _;
//==================================================================
int a[100],b[100];
//==================================================================
int main()
{
for(scanf("%d",&_);_;_--)
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]);
sort(a+1,a+1+n);
sort(b+1,b+1+n);
int ans=0,r=0;
for(int i=1;i<=k;i++)
{
if(a[i]>=b[n-i+1]) break;
r=i;
if(a[i]<b[n-i+1]) ans+=b[n-i+1];
}
for(int j=r+1;j<=n;j++) ans+=a[j];
printf("%d
",ans);
}
return 0;
}
codeforces-1353-C. Board Moves
题意:上图把
就是这样,这是n=7的情况,我们可以把这个图分成8部分,每部分都是i*i for(ll i=1;i<=n/2;i++) ans+= i * i *8;
注意循环里要开long long
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a)&-(a))
#define clean(a,b) memset(a,b,sizeof(a))
const int mod = 1e9 + 7;
const int inf=0x3f3f3f3f;
const int maxn = 2e5+9;
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
int _;
//==================================================================
int a[100],b[100];
//==================================================================
int main()
{
for(scanf("%d",&_);_;_--)
{
int n;
scanf("%d",&n);
ll ans=0;
for(ll i=1;i<=n/2;i++)
{
ans+=i*i*8;
}
printf("%lld
",ans);
}
return 0;
}
codeforces-1353-D. Constructing the Array
题意:一个长度为 n 的数组,初始值全部为 0
每次选择其中最长的一段全0连续子数组,如果多个并列最长,取最左边的那个,并标记其左右区间 L R
如果这个子数组包含的元素个数为奇数(R-L+1为奇数),则将这一段区间最中间那个位置标记上数字
如果这个子数组包含的元素个数为偶数,则将这一段区间内中间靠左的那个位置标记上数字
数字依次标记 1~n,最后输出这个数组
每次选择其中最长的一段全0连续子数组,那么我们可以搞一个优先队列,每个元素就是一整段连续的0,按照全0连续子数组的长度来排序,每次从队列取出来的时候,给中间的赋值,然后再把他掰断扔进队列,直到长度都为1
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a)&-(a))
#define clean(a,b) memset(a,b,sizeof(a))
const int mod = 1e9 + 7;
const int inf=0x3f3f3f3f;
const int maxn = 2e5+9;
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
int _;
//==================================================================
//==================================================================
int ans[maxn];
struct node
{
int l,r,di;
bool operator<(const node&a) const
{
return di==a.di&&l>a.l||di<a.di;
}
};
priority_queue<node>qu;
int main()
{
for(scanf("%d",&_);_;_--)
{
int n;
scanf("%d",&n);
if(n==1)
{
printf("1
");
continue;
}
if(n==2)
{
printf("1 2
");
continue;
}
int cnt=1;
node now;
now.l=1;
now.r=n;
now.di=(now.r-now.l+1);
qu.push(now);
while(!qu.empty())
{
now=qu.top();
qu.pop();
node a,b;
int mid=(now.l+now.r)/2;
ans[mid]=cnt;
cnt++;
if(now.l!=mid)
{
a.l=now.l;
a.r=mid-1;
a.di=a.r-a.l+1;
qu.push(a);
}
if(now.r!=mid)
{
b.l=mid+1;
b.r=now.r;
b.di=b.r-b.l+1;
qu.push(b);
}
}
for(int i=1; i<n; i++) printf("%d ",ans[i]);
printf("%d
",ans[n]);
}
return 0;
}
codeforces-1353-E. K-periodic Garland
题意:有一个01串,0代表灯关着1代表开着,给你一个k,开 或者关灯 让这个01串每对相邻的1差k-1
感觉是一个dp呢
枚举1-n dp[i]=min(他前面都是0从他开始是1需要开关灯的次数,dp[i-k]+(i-k到i这段需要关灯的次数)+(如果本来是关的那么打开,开的就不用加))
ans=min(ans,dp[i]+(以他做结尾后面都是0需要改的次数))
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a)&-(a))
#define clean(a,b) memset(a,b,sizeof(a))
const int mod = 1e9 + 7;
const int inf=0x3f3f3f3f;
const int maxn = 1e6+9;
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
int _;
//==================================================================
int a[maxn],hsum[maxn],dp[maxn];
//==================================================================
int main()
{
for(scanf("%d",&_);_;_--)
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%1d",&a[i]);
for(int i=1;i<=n;i++)
{
if(a[i]==1) hsum[i]=hsum[i-1]+1;
else hsum[i]=hsum[i-1];
}
int ans=inf;
for(int i=1;i<=n;i++)
{
if(i>k) dp[i]=min(hsum[i-1],dp[i-k]+hsum[i-1]-hsum[i-k])+(a[i]==0);
else dp[i]=hsum[i-1]+(a[i]==0);
ans=min(ans,dp[i]+hsum[n]-hsum[i]);
}
ans=min(ans,hsum[n]);
printf("%d
",ans);
}
return 0;
}