CF#401(Div.2) 解题报告
2017-02-24 21:40
309 查看
,近期最水的一场cf,跪成狗了!!。,。状态好烂
b两个手残
e有一种情况没考虑到
c没有想到非常简单的正解
以后还是要要求自己把能拿到的分都拿到啊。。要不然跪得太惨了
打表或模拟
第一个人的数不变,第二个人想将其拥有的数字重新排列,使:
1、自己被×的次数最少
2、第一个人被×的次数最多
注意两个答案可能出自两种方案
贪心
第一问,贪心地覆盖小的(用大于等于的数)
第二问,同理(用大于的数)
统计答案即可
ans(i)表示第i行中存在的一列最多到哪一行不降
然后用ans(i)判断就行了
需要满足删掉最少的字符
求出删后的字符串们
从后往前倒着删
如果前面的字典序小于后面的,不删
大于,将刚开始大于的一直到最后删掉
选出一个物品序列,满足对于所有的j<i,bj≤bi,bj>ai,在这个前提下使∑hi最大
首先按照b为第一关键字,a为第二关键字从小到大排序
dp,f(i)表示前i个,第i个必须选的最大值
线段树优化
注意必须双关键字排序,因为要让能先选的a尽量先选
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); }
相关文章推荐
- Codeforces Round #283(Div.2) A,B,C,D,E 解题报告
- CF#410(Div.2) 解题报告
- Codeforces #200 (Div.2) E. Read Time 解题报告
- CF#386(Div.2) 解题报告
- codeforces #198 div.2 解题报告
- CF Round 415 Div.2解题报告
- Codeforces Round #285(Div.2) A,B,C 解题报告
- CF#403(Div.2) 解题报告
- 解题报告:codeforces #339(Div.2)B.Gena's Code
- Codeforces #191(Div.2)解题报告
- CF#384 (Div.2) 解题报告
- 【解题报告】BestCoder Round #77 (div.2)
- CF#398(Div.2) 解题报告
- BestCoder Round #77 (div.2)解题报告
- hdu 5326 - Work(递归)解题报告
- COGS 4.双服务点设置 解题报告
- 洛谷 2014 选课 树形DP 解题报告
- pku_2054 dp Color a tree dp 解题报告
- poj2230 解题报告
- 字符序列 解题报告