Codeforces Round #220 (Div. 2)
来源:互联网 发布:归来。知乎 编辑:程序博客网 时间:2024/06/06 09:27
这场单独的div2真的好难,trick太多。A题几乎写了的人都是错的,各种hack。。。B题出题人想错了,最后unrated了 。我B题错的和出题人一样。。。最后只过了C。。。
A:
把4个位移式子相互叠加一下可以推出类似(x,y-2b)的式子。
- (x - a, y - b)
- (x + a, y - b)
就是一个坐标可以不变,另一个坐标偏移2次。前提是x要有足够的空间上下各偏移一次。难么只要2个坐标变换次数相差偶数,就能调整成一样。满足条件后,答案取二者中偏移次数多的。枚举4个角即可。
code:
#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <string>#include <math.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;#define N 100010#define ALL(x) x.begin(),x.end()#define CLR(x,a) memset(x,a,sizeof(x))typedef long long ll;typedef pair<int,int> PI;const int INF = 0x3fffffff;const int MOD = 100000007;const double EPS = 1e-7;bool move=true;int ans=INF;void solve(int x,int y){if(!move && (x||y)) return ;if(abs(x-y)%2) return ;ans=min(ans,max(x,y));}int main(){int n,m,i,j,a,b;scanf("%d%d%d%d%d%d",&n,&m,&i,&j,&a,&b);if( (i-1<a && n-i<a) || (j-1<b && m-j<b) ) move=false;if((i-1)%a==0 && (j-1)%b==0) solve((i-1)/a, (j-1)/b);if((i-1)%a==0 && (m-j)%b==0) solve((i-1)/a, (m-j)/b);if((n-i)%a==0 && (j-1)%b==0) solve((n-i)/a, (j-1)/b);if((n-i)%a==0 && (m-j)%b==0) solve((n-i)/a, (m-j)/b);if(ans==INF) puts("Poor Inna and pony!");else printf("%d\n",ans);return 0;}
B:
对于一段连续的区间[l,r],满足(digit[i]+dight[i+1])==9,(l<=i<r)。设长度为n。
那么这段区间内,变换成最多9的情况有多少种呢?
1.n为偶数,显然变成n/2个9,只有一种变法。
2.n为奇数,有(n+1)/2种变成最多9的变法。这里最开始我认为只有2种,即从左往右开始变,和从右往左开始变,出题人也是这么认为的。。。。然后过了pre我就没管了。。。事实上能忽略一个奇数位的数字,剩下的数字个数为偶数,能全用完变成9。那么答案就是奇数位数字的个数。
累乘每段区间的种数就是答案了。
code:
#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <string>#include <math.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;#define N 200010#define ALL(x) x.begin(),x.end()#define CLR(x,a) memset(x,a,sizeof(x))typedef long long ll;typedef pair<int,int> PI;const int INF = 0x3fffffff;const int MOD = 100000007;const double EPS = 1e-7;char s[N];int dp[N];int main(){scanf("%s",s);for(int i=0;s[i];i++) s[i]-='0';int star=0;int n=strlen(s);ll ans=1;for(int i=0;i<n-1;i++){if(s[i]+s[i+1]!=9){if(i-star+1>2 && (i-star+1)%2 ) ans*=(i-star+2)/2;star=i+1;}}if(n-star>2 && (n-star)%2) ans*=(n-star+1)/2;printf("%I64d\n",ans);return 0;}
C:
可以记忆化搜索,dp[x][y]表示从这点出发,最多走出几个“DIMA”。不过比赛的时候,我第一反应是建图,写个拓扑排序。建图就是对于所有“DIMA”的路径,D到A连一条权值为1的边。然后所有A到D连一条权值为0的边,都是有向的。
下面代码是拓扑排序+dp的做法。
code:
#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <string>#include <math.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;#define N 1024#define ALL(x) x.begin(),x.end()#define CLR(x,a) memset(x,a,sizeof(x))typedef long long ll;typedef pair<int,int> PI;const int INF = 0x3fffffff;const int MOD = 100000007;const double EPS = 1e-7;const int dx[] = {-1, 1, 0, 0};const int dy[] = {0, 0, -1, 1};int n,m,U;char c[4]={'D','I','M','A'};char mp[N][N];bool g[N][N];vector<PI> e[N*N];int has;bool vis[N*N];void dfs(int x,int y,int step){if(step==4){has++;vis[m*x+y]=true;e[U].push_back((PI){m*x+y,1});return ;}for(int i=0;i<4;i++){int xx=dx[i]+x;int yy=dy[i]+y;if(xx<0 || xx>=n || yy<0 || yy>=m) continue;if(mp[xx][yy]==c[step]){dfs(xx,yy,step+1);}}}int dp[N*N];int in[N*N];void topSort(){int num=0,cnt=0;for(int i=0;i<n*m;i++){if(vis[i]) cnt++;for(int j=0;j<e[i].size();j++)in[e[i][j].first]++;}queue<int> que;for(int i=0;i<n*m;i++){if(in[i]==0 && vis[i]) que.push(i);}while(!que.empty()){int u=que.front();que.pop();num++;for(int i=0;i<e[u].size();i++){int v=e[u][i].first;dp[v]=max(dp[v],dp[u]+e[u][i].second);if(--in[v]==0) que.push(v);}}if(num<cnt)puts("Poor Inna!");elseprintf("%d\n",*max_element(dp,dp+n*m));}int main(){scanf("%d%d",&n,&m);for(int i=0;i<n;i++) scanf("%s",mp[i]);for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(mp[i][j]=='D'){U=m*i+j;vis[U]=true;dfs(i,j,1);}for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(mp[i][j]=='A'){U=m*i+j;vis[U]=true;for(int k=0;k<4;k++){int xx=dx[k]+i;int yy=dy[k]+j;if(xx<0 || xx>=n || yy<0 || yy>=m) continue;if(mp[xx][yy]=='D'){vis[m*xx+yy]=true;e[U].push_back((PI){m*xx+yy,0});}}}if(has) topSort();else puts("Poor Dima!");return 0;}
D:
二分+树状数组
先把每次删除的k记录下来,然后把所有01元素按顺序都加到序列里,最后统一进行删除操作。
我们用1标记某个位置上的元素是否存在。如果sum(i)==p 且 sum(i)-sum(i-1)==1 那么说明,第i个元素目前是序列里的第p个1(也就是经过一些删除操作后,它现在排在第p个)。
对于删除操作,二分出要删除元素的位置,把它清零就好了。
code:
#include <algorithm>#include <iostream>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <string>#include <math.h>#include <vector>#include <queue>#include <stack>#include <cmath>#include <list>#include <set>#include <map>using namespace std;#define N 1000010#define ALL(x) x.begin(),x.end()#define CLR(x,a) memset(x,a,sizeof(x))typedef long long ll;typedef pair<int,int> PI;const int INF = 0x3fffffff;const int MOD = 1000000007;const double EPS = 1e-7;int a[N],c[N],d[N],t[N];int n,m,num;void add(int i,int x){for(;i<=num;i+= -i&i) c[i]+=x;}int sum(int i){if(i>num) return num+1;int ans=0;for(;i>=1;i-= -i&i) ans+=c[i];return ans;}void remove(int end){vector<int> pos;for(int i=1;i<=end;i++){int l=1,r=num+1;while(l<r){int mid=(l+r)>>1;int x=sum(mid);if(x<a[i] || (x==a[i] && sum(mid)-sum(mid-1)==1) ) l=mid+1;else r=mid;}pos.push_back(r-1);}for(int i=0;i<pos.size();i++) add(pos[i],-1);}int main(){int op,len=0,T=0;scanf("%d%d",&m,&n);for(int i=1;i<=n;i++) scanf("%d",a+i);while(m--){scanf("%d",&op);if(op==-1){int end=upper_bound(a+1,a+n+1,len)-a-1;len-=end;t[T++]=end;}else{num++;len++;d[num]=op;}}for(int i=1;i<=num;i++) add(i,1);for(int i=0;i<T;i++) remove(t[i]);bool can=true;for(int i=1;i<=num;i++) if(sum(i)-sum(i-1)==1){printf("%d",d[i]); can=false;}if(can) puts("Poor stack!");return 0;}
- Codeforces Round #220 (Div. 2)
- Codeforces Round #220 (Div. 2)
- Codeforces Round #220 (Div. 2)
- Codeforces Round #220 (Div. 2)
- Codeforces Round #220 (Div. 2)A-C
- Codeforces Round #220 (Div. 2) ABCD
- Codeforces Round #220 (Div. 2) A题
- Codeforces Round #102 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #103 (Div. 2)
- Codeforces Round #104 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #105 (Div. 2)
- Codeforces Round #107 (Div. 2)
- Codeforces Round #108 (Div. 2)
- Codeforces Round #110 (Div. 2)
- Codeforces Round #122 (Div. 2)
- Codeforces Round #121 (Div. 2)
- PHP 真正多线程的使用
- gdb 打印字符串的全部内容
- Android之向中国天气网发送GET请求获取JSON数据实例
- 菜鸟之学习STM32(一)暂停C51的复习,开始学习STM32
- 浅谈千万级PV/IP规模高性能高并发网站架构
- Codeforces Round #220 (Div. 2)
- 文字省略号
- 年轻时不做会后悔的八件事
- Android串口调试
- Sublime Text 2 入门及技巧
- C++闭包: Lambda Functions in C++11
- J-Link V8和openOCD结合调试程序
- 拼装json字符串
- ExecutorService线程池