codeforces Intel Code Challenge Final Round (div.1 + div.2 combined)
比赛水掉3题rk559 rating+115
赛后切掉C
n年没打cf了终于又重新变蓝了,果然太弱。。。
1.A题 Checking the Calendar
给定两个星期几,问是否可能分别是两个月的第一天。
水题暴力枚举月份
#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<string> #include<cctype> #include<stack> #include<queue> #include<set> #include<sstream> #include<map> using namespace std; #define FORD(i,k,n) for(int i=n;i>=k;i--) #define FOR(i,k,n) for(int i=k;i<=n;i++) #define CLR(a,b) memset(a,b,sizeof(a)); #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define ll long long #define LL long long #define ull unsigned long long #define i64 long long #define u32 unsigned int #define u64 unsigned long long #define ptb(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;} #define pta(i,a,f,b) {FOR(i,f,b) cout<<a[i]<<" "; printf("\n");} #define pt(a,b) cout<<a<<"="<<b<<endl #define pt1(a) cout<<a<<endl #define pt2(a,b) cout<<a<<" "<<b<<endl #define pt3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl #define pt4(a,b,c,d) cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl #define ptl1 cout<<"-------------"<<endl #define ptl2 cout<<"~~~~~~~~~~~~~~~~"<<endl #define fp freopen("in.txt","r",stdin) #define maxn (100050) int n,m,k; int d[4][2]={ {1,1},{-1,1},{-1,-1},{1,-1} }; struct node { int x,y; ll tm; bool operator<(const node&rhs)const { if(x!=rhs.x) return x<rhs.x; else if(y!=rhs.y)return y<rhs.y; else return tm<rhs.tm; } }p[maxn]; int nume; node mp[4][maxn*20]; void read() { cin>>n>>m>>k; FOR(i,1,k) { cin>>p[i].x>>p[i].y; } } void change(int &x,int &y,int &dir,int& dd) { int nx,ny; if(dir==0) { dd=min(n-x,m-y); nx=dd+x,ny=dd+y; if(nx==n&&ny==m) ; else if(nx==n) dir=1; else dir=3; } else if(dir==1) { dd=min(x,m-y); nx=x-dd,ny=dd+y; if(nx==0&&ny==m) ; else if(nx==0) dir=0; else dir=2; } else if(dir==2) { dd=min(x,y); nx=x-dd,ny=y-dd; if(nx==0&&ny==0) ; else if(nx==0) dir=3; else dir=1; } else { dd=min(n-x,y); nx=x+dd,ny=y-dd; if(nx==n&&ny==0) ; else if(nx==n) dir=2; else dir=0; } x=nx;y=ny; } void preprocess() { int x=0,y=0,dir=0; ll sum=0; int cnt=0; while(cnt<=4*(m+n)) { node tmp;tmp.x=x;tmp.y=y;tmp.tm=sum; int dd=0; mp[dir][nume++]=tmp; change(x,y,dir,dd); sum+=dd; cnt++; // ptl2; } FOR(j,0,3) sort(mp[j],mp[j]+nume); } void solve() { FOR(i,1,k) { ll ans=LLINF; FOR(j,0,3) { int x=p[i].x,y=p[i].y,dir=j,dd=0; change(x,y,dir,dd); node tmp; tmp.x=x;tmp.y=y;tmp.tm=0; if(j==0) dir=2; else if(j==2) dir=0; else if(j==1) dir=3; else dir=1; FOR(t,0,3){ int p=lower_bound(mp[t],mp[t]+nume,tmp)-mp[t]; if(p>=0&&p<nume&&mp[t][p].x==x&&mp[t][p].y==y) { ans=min(ans,mp[t][p].tm+dd); } } } printf("%I64d\n",ans==LLINF?-1:ans); } } int main() { { read(); preprocess(); solve(); } return 0; }
2.B题 Batch Sort
给定矩阵要求最后每一行都排好序,支持操作a.每一行最多选两个交换一次 b.最后最多选两列整体交换一次。
似乎有很多人在这题上翻船了,估计是想复杂了,因为规模太小暴力枚举b,然后看看a行不行就行了。
#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<string> #include<cctype> #include<stack> #include<queue> #include<set> #include<sstream> #include<map> using namespace std; #define FORD(i,k,n) for(int i=n;i>=k;i--) #define FOR(i,k,n) for(int i=k;i<=n;i++) #define CLR(a,b) memset(a,b,sizeof(a)); #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define ll long long #define LL long long #define ull unsigned long long #define i64 long long #define u32 unsigned int #define u64 unsigned long long #define ptb(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;} #define pta(i,a,f,b) {FOR(i,f,b) cout<<a[i]<<" "; printf("\n");} #define pt(a,b) cout<<a<<"="<<b<<endl #define pt1(a) cout<<a<<endl #define pt2(a,b) cout<<a<<" "<<b<<endl #define pt3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl #define pt4(a,b,c,d) cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl #define ptl1 cout<<"-------------"<<endl #define ptl2 cout<<"~~~~~~~~~~~~~~~~"<<endl #define fp freopen("in.txt","r",stdin) #define maxn 30 int T,N,M,mat[maxn][maxn],tmp[maxn][maxn],a[maxn]; void read() { cin>>N>>M; FOR(i,1,N) FOR(j,1,M) cin>>mat[i][j]; } void preprocess() { } int work(int i,int j) { int flg=1; FOR(r,1,N) { swap(tmp[r][i],tmp[r][j]); } FOR(r,1,N) { FOR(c,1,M) a[c]=tmp[r][c]; sort(a+1,a+1+M); int cnt=0; FOR(c,1,M) if(a[c]!=tmp[r][c]) cnt++; if(cnt>2) flg=0; } return flg; } void solve() { int flg=0; FOR(i,1,M) { FOR(j,i,M) { memcpy(tmp,mat,sizeof(tmp)); flg|=work(i,j); } } if(flg) puts("YES"); else puts("NO"); } int main() { { read(); solve(); } return 0; }
3.C题 Ray tracing
给定一个网格10w*10w,从(0,0)出发光线会反射,询问10w次某一个点能否到达。
比赛的时候是想的暴力模拟,记录所有经过的点,mle。于是尝试只记录边界点,tle。
正确的思路是暴力只模拟墙上落点,预处理出来。然后每个询问必然光线来自于墙上某个点,于是二分查找有没有这种点,注意用map记录落点会mle。
比赛的时候确实有过这种落点思路,但是没想到每个询问必然光线来自于墙上某个点,遗憾。。。
#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<string> #include<cctype> #include<stack> #include<queue> #include<set> #include<sstream> #include<map> using namespace std; #define FORD(i,k,n) for(int i=n;i>=k;i--) #define FOR(i,k,n) for(int i=k;i<=n;i++) #define CLR(a,b) memset(a,b,sizeof(a)); #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define ll long long #define LL long long #define ull unsigned long long #define i64 long long #define u32 unsigned int #define u64 unsigned long long #define ptb(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;} #define pta(i,a,f,b) {FOR(i,f,b) cout<<a[i]<<" "; printf("\n");} #define pt(a,b) cout<<a<<"="<<b<<endl #define pt1(a) cout<<a<<endl #define pt2(a,b) cout<<a<<" "<<b<<endl #define pt3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl #define pt4(a,b,c,d) cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl #define ptl1 cout<<"-------------"<<endl #define ptl2 cout<<"~~~~~~~~~~~~~~~~"<<endl #define fp freopen("in.txt","r",stdin) #define maxn (100050) int n,m,k; int d[4][2]={ {1,1},{-1,1},{-1,-1},{1,-1} }; struct node { int x,y; ll tm; bool operator<(const node&rhs)const { if(x!=rhs.x) return x<rhs.x; else if(y!=rhs.y)return y<rhs.y; else return tm<rhs.tm; } }p[maxn]; int nume; node mp[4][maxn*20]; void read() { cin>>n>>m>>k; FOR(i,1,k) { cin>>p[i].x>>p[i].y; } } void change(int &x,int &y,int &dir,int& dd) { int nx,ny; if(dir==0) { dd=min(n-x,m-y); nx=dd+x,ny=dd+y; if(nx==n&&ny==m) ; else if(nx==n) dir=1; else dir=3; } else if(dir==1) { dd=min(x,m-y); nx=x-dd,ny=dd+y; if(nx==0&&ny==m) ; else if(nx==0) dir=0; else dir=2; } else if(dir==2) { dd=min(x,y); nx=x-dd,ny=y-dd; if(nx==0&&ny==0) ; else if(nx==0) dir=3; else dir=1; } else { dd=min(n-x,y); nx=x+dd,ny=y-dd; if(nx==n&&ny==0) ; else if(nx==n) dir=2; else dir=0; } x=nx;y=ny; } void preprocess() { int x=0,y=0,dir=0; ll sum=0; int cnt=0; while(cnt<=4*(m+n)) { node tmp;tmp.x=x;tmp.y=y;tmp.tm=sum; int dd=0; mp[dir][nume++]=tmp; change(x,y,dir,dd); sum+=dd; cnt++; // ptl2; } FOR(j,0,3) sort(mp[j],mp[j]+nume); } void solve() { FOR(i,1,k) { ll ans=LLINF; FOR(j,0,3) { int x=p[i].x,y=p[i].y,dir=j,dd=0; change(x,y,dir,dd); node tmp; tmp.x=x;tmp.y=y;tmp.tm=0; if(j==0) dir=2; else if(j==2) dir=0; else if(j==1) dir=3; else dir=1; FOR(t,0,3){ int p=lower_bound(mp[t],mp[t]+nume,tmp)-mp[t]; if(p>=0&&p<nume&&mp[t][p].x==x&&mp[t][p].y==y) { ans=min(ans,mp[t][p].tm+dd); } } } printf("%I64d\n",ans==LLINF?-1:ans); } } int main() { { read(); preprocess(); solve(); } return 0; }
4.D题 Dense subsequence
给定一个字母序列,要求选定子序列使得原来序列每m个连续子序列中至少包含一个选定子序列的元素。要求字典序最小。
从小到大枚举字母。如果尽量少的选当前字母能够达成条件,退出;否则删除这轮选的,全选序列中该字母。
#include<cstdio> #include<cstring> #include<cstdlib> #include<vector> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<string> #include<cctype> #include<stack> #include<queue> #include<set> #include<sstream> #include<map> using namespace std; #define FORD(i,k,n) for(int i=n;i>=k;i--) #define FOR(i,k,n) for(int i=k;i<=n;i++) #define CLR(a,b) memset(a,b,sizeof(a)); #define INF 0x3f3f3f3f #define LLINF 0x3f3f3f3f3f3f3f3f #define ll long long #define LL long long #define ull unsigned long long #define i64 long long #define u32 unsigned int #define u64 unsigned long long #define ptb(b,a){int tmp=a;string s;do{s+=tmp%2+'0';tmp/=2;}while(tmp);reverse(s.begin(),s.end());cout<<"bin "<<b<<"="<<s<<endl;} #define pta(i,a,f,b) {FOR(i,f,b) cout<<a[i]<<" "; printf("\n");} #define pt(a,b) cout<<a<<"="<<b<<endl #define pt1(a) cout<<a<<endl #define pt2(a,b) cout<<a<<" "<<b<<endl #define pt3(a,b,c) cout<<a<<" "<<b<<" "<<c<<endl #define pt4(a,b,c,d) cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl #define ptl1 cout<<"-------------"<<endl #define ptl2 cout<<"~~~~~~~~~~~~~~~~"<<endl #define fp freopen("in.txt","r",stdin) #define maxn 200000 int T,N,m,flg; string ans; char s[maxn]; int last; int vis[maxn]; void read() { scanf("%d %s",&m,s+1); } void preprocess() { } void solve() { int len=strlen(s+1); FOR(i,'a','z') { last=0; int l=1,r=m; FOR(k,1,m) { if((last==0&&s[k]==i)||(s[k]<=s[last])||vis[k]) last=k; } string tmp; if(last&&s[last]==i) tmp+=i; // pt1(last); while(r<len&&last) { l++; r++; if(last>=l&&last<=r) continue; else { last=0; FOR(k,l,r) { if((last==0&&s[k]==i)||(s[k]<=s[last])||vis[k]) last=k; } if(last&&s[last]==i) { tmp+=i; } } // pt4(last,l,r,ans); } if(last) { ans+=tmp; break; } else { FOR(k,1,len) { if(s[k]==i) { vis[k]=1; ans+=i; } } } } cout<<ans<<endl; } int main() { { read(); solve(); } return 0; }