您的位置:首页 > 其它

CF#401(Div.2) 解题报告

2017-02-24 21:40 309 查看
,近期最水的一场cf,跪成狗了!!。,。状态好烂

b两个手残

e有一种情况没考虑到

c没有想到非常简单的正解

以后还是要要求自己把能拿到的分都拿到啊。。要不然跪得太惨了

A

题意简述

0,1,2三个杯子,放入一个小球,然后先将前两个交换,再将后两个交换,不停进行,交换n次之后小球在杯子x里,问刚开始小球在哪里

数据范围

1≤n≤2∗109

题解

交换的规则使杯子6次一循环

打表或模拟

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<ctime>
#include<cmath>
#include<map>
using namespace std;

int n,x;
int a[10][10];

int main()
{
a[1][0]=1,a[1][1]=0,a[1][2]=2;
a[2][0]=1,a[2][1]=2,a[2][2]=0;
a[3][0]=2,a[3][1]=1,a[3][2]=0;
a[4][0]=2,a[4][1]=0,a[4][2]=1;
a[5][0]=0,a[5][1]=2,a[5][2]=1;
a[0][0]=0,a[0][1]=1,a[0][2]=2;
scanf("%d",&n);n%=6;
scanf("%d",&x);
printf("%d\n",a
[x]);
}


B

题意简述

有两个人,每个人有一个n位整数,两个人按位比较,如果某一个人的比另一个人大则小的人被×

第一个人的数不变,第二个人想将其拥有的数字重新排列,使:

1、自己被×的次数最少

2、第一个人被×的次数最多

注意两个答案可能出自两种方案

数据范围

1≤n≤1000

题解

很容易知道数字顺序是无关的,只与每一个数出现的次数有关

贪心

第一问,贪心地覆盖小的(用大于等于的数)

第二问,同理(用大于的数)

统计答案即可

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<ctime>
#include<cmath>
#include<map>
using namespace std;

int n,now,ans1,ans2;
int a[20],b[20];
char s[1005];

int main()
{
scanf("%d",&n);
scanf("%s",s);
for (int i=0;i<n;++i) ++a[s[i]-'0'];
scanf("%s",s);
for (int i=0;i<n;++i) ++b[s[i]-'0'];
for (int i=9;i>=0;--i) b[i]+=b[i+1];

now=b[0];
for (int i=0;i<=9;++i)
{
now=min(now,b[i]);
if (a[i]>now) ans1+=a[i]-now,now=0;
else now-=a[i];
}

now=b[1];
for (int i=0;i<=9;++i)
{
now=min(now,b[i+1]);
if (a[i]>now) ans2+=now,now=0;
else ans2+=a[i],now-=a[i];
}

printf("%d\n%d\n",ans1,ans2);
}


C

题意简述

给出一个n×m的矩阵,每一次询问lr,问是否存在一列满足第l行到第r行的数不降

数据范围

1≤nm≤105,1≤k≤105

题解

f(i,j)表示(i,j)这个点向后最多到哪一行不降

ans(i)表示第i行中存在的一列最多到哪一行不降

然后用ans(i)判断就行了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<ctime>
#include<cmath>
#include<map>
using namespace std;

int n,m,k,l,r;
int ans[100005];

int main()
{
scanf("%d%d",&n,&m);
int a[n+1][m+1],f[n+1][m+1];
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
scanf("%d",&a[i][j]);
ans
=n;
for (int i=1;i<=m;++i)
{
f
[i]=n;
for (int j=n-1;j>=1;--j)
{
if (a[j][i]<=a[j+1][i]) f[j][i]=f[j+1][i];
else f[j][i]=j;
ans[j]=max(ans[j],f[j][i]);
}
}
scanf("%d",&k);
while (k--)
{
scanf("%d%d",&l,&r);
if (ans[l]>=r) puts("Yes");
else puts("No");
}
}


D

题意简述

给出n的字符串,对于每一个字符串可以删掉任意一个后缀,使删后的字符串字典序不降

需要满足删掉最少的字符

求出删后的字符串们

题解

贪心

从后往前倒着删

如果前面的字典序小于后面的,不删

大于,将刚开始大于的一直到最后删掉

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<ctime>
#include<cmath>
#include<map>
using namespace std;
#define N 1000005

int n,len,ls,l,r,head
,tail
;
char a
,s
;

int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
{
scanf("%s",a);len=strlen(a);
head[i]=ls;
for (int j=0;j<len;++j) s[ls++]=a[j];
}
for (int i=1;i<n;++i) tail[i]=head[i+1]-1;tail
=ls-1;
for (int i=n;i>=2;--i)
{
l=head[i-1],r=head[i];
while (l<=head[i]&&r<=tail[i])
{
if (s[l]>s[r]) {tail[i-1]=l-1;break;}
else if (s[l]<s[r]) {l=tail[i-1]+1;break;}
++l,++r;
}
tail[i-1]=min(tail[i-1],l-1);
}
for (int i=1;i<=n;++i)
{
for (int j=head[i];j<=tail[i];++j)
putchar(s[j]);
putchar('\n');
}
}


E

题意简述

每一个物品有三个指标a,b,h

选出一个物品序列,满足对于所有的j<i,bj≤bi,bj>ai,在这个前提下使∑hi最大

数据范围

1≤n≤105,1≤ai,bi,hi≤109,bi>ai

题解

一眼题

首先按照b为第一关键字,a为第二关键字从小到大排序

dp,f(i)表示前i个,第i个必须选的最大值

线段树优化

注意必须双关键字排序,因为要让能先选的a尽量先选

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<ctime>
#include<cmath>
#include<map>
using namespace std;
#define LL long long
#define N 100005

int n,LSH,lsh[N*2];
struct data{int a,b,h;}p
;
LL maxn[N*8],f
,ans;

int find(int x)
{
int l=1,r=LSH,mid,ans;
while (l<=r)
{
mid=(l+r)>>1;
if (lsh[mid]>=x) ans=mid,r=mid-1;
else l=mid+1;
}
return ans;
}
int cmp(data a,data b)
{
return a.b<b.b||a.b==b.b&&a.a<b.a;
}
void update(int now)
{
maxn[now]=max(maxn[now<<1],maxn[now<<1|1]);
}
void change(int now,int l,int r,int x,LL v)
{
int mid=(l+r)>>1;
if (l==r)
{
maxn[now]=max(maxn[now],v);
return;
}
if (x<=mid) change(now<<1,l,mid,x,v);
else change(now<<1|1,mid+1,r,x,v);
update(now);
}
LL query(int now,int l,int r,int lr,int rr)
{
int mid=(l+r)>>1;
LL ans=0;
if (lr<=l&&r<=rr) return maxn[now];
if (lr<=mid) ans=max(ans,query(now<<1,l,mid,lr,rr));
if (mid+1<=rr) ans=max(ans,query(now<<1|1,mid+1,r,lr,rr));
return ans;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
{
scanf("%d%d%d",&p[i].a,&p[i].b,&p[i].h);
lsh[++LSH]=p[i].a,lsh[++LSH]=p[i].b;
}
sort(lsh+1,lsh+LSH+1);LSH=unique(lsh+1,lsh+LSH+1)-lsh-1;
for (int i=1;i<=n;++i)
p[i].a=find(p[i].a),p[i].b=find(p[i].b);
sort(p+1,p+n+1,cmp);
f[1]=(LL)p[1].h;change(1,1,LSH,p[1].b,f[1]);
for (int i=2;i<=n;++i)
{
f[i]=query(1,1,LSH,p[i].a+1,p[i].b);
f[i]+=(LL)p[i].h;
change(1,1,LSH,p[i].b,f[i]);
}
ans=0LL;
for (int i=1;i<=n;++i) ans=max(ans,f[i]);
printf("%I64d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: