Codeforces Round #653 (Div. 3)
Posted ticmis
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #653 (Div. 3)相关的知识,希望对你有一定的参考价值。
题解 Codeforces Round #653 (Div. 3)
本来是兴起,打算打一场div3录下来的,但是...这场div3真是把我的心态打崩了>﹏< 刚开始pc上的chrome题面latex总是加载不出来;后来的E2贪心爆炸;改题整整改了两天,一道题改了十多遍...
A. Required Remainder
英文阅读理解题。先令(ans=frac{n}{x} imes x + y),如果(ans>n) 就令(ans-=x) 即可
#include <bits/stdc++.h>
using namespace std;
#define lor(a,b,c) for(register int a=b;a<=c;++a)
#define ror(a,b,c) for(register int a=c;a>=b;--a)
inline void work(){
int x,y,n; scanf("%d%d%d",&x,&y,&n);
int res=(n/x)*x+y; if(res>n) res-=x;
printf("%d
",res);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
int qwq=1; cin>>qwq; while(qwq--) work();
return 0;
}
B. Multiply by 2, divide by 6
这道题也是很基础。如果(n)包含(2)和(3)以外的因数一定不合法;否则(n=2^a imes 3^b),若(a>b)也是不合法的;否则答案是((b-a)+b)
#include <bits/stdc++.h>
using namespace std;
#define lor(a,b,c) for(register int a=b;a<=c;++a)
#define ror(a,b,c) for(register int a=c;a>=b;--a)
inline void work(){
int n; cin>>n;
int res2=0,res3=0;
while(n%2==0) n/=2,res2++;
while(n%3==0) n/=3,res3++;
if(n!=1) {puts("-1"); return;}
if(res2<=res3) printf("%d
",(res3-res2)+res3);
else puts("-1");
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
int qwq=1; cin>>qwq; while(qwq--) work();
return 0;
}
Move Brackets
一道比较明显的贪心题,并没有太多可作记录的
#include <bits/stdc++.h>
using namespace std;
#define lor(a,b,c) for(register int a=b;a<=c;++a)
#define ror(a,b,c) for(register int a=c;a>=b;--a)
const int N=55;
int n; char s[N];
inline void work(){
cin>>n; cin>>s+1;
int lef=0,cnt=0;
lor(i,1,n){
if(s[i]==‘(‘){
++lef;
}
else{
if(lef) lef--; else cnt++;
}
}
printf("%d
",cnt);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
int qwq=1; cin>>qwq; while(qwq--) work();
return 0;
}
Zero Remainder Array
把握住同余的一些小性质,也是很也好做出来的。
#include <bits/stdc++.h>
using namespace std;
#define lor(a,b,c) for(register int a=b;a<=c;++a)
#define ror(a,b,c) for(register int a=c;a>=b;--a)
typedef long long ll;
const int N=2e5+5;
int n,k,a[N],b[N];
inline void work(){
scanf("%d%d",&n,&k); lor(i,1,n) scanf("%d",&a[i]);
lor(i,1,n) b[i]=(k-a[i]%k)%k; sort(b+1,b+1+n);
ll ans=0;
for(register int i=1;i<=n;){
register int j=i; while(j<n&&b[i]==b[j+1]) ++j;
if(b[i]) ans=max(ans,1ll+(1ll*(j-i+1)-1)*(ll)k+(ll)b[i]);
i=j+1;
}
printf("%lld
",ans);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
int qwq=1; cin>>qwq; while(qwq--) work();
return 0;
}
E1 Reading Books (easy version)
这道题就是噩梦的开始...
本题是简易版本,可以发现:(a=0,b=0)的书一概没用;要么是一本(a=b=1)的书,要么是(a=1,b=0)和(a=0,b=1)的两本书。
观察完性质后,可以用优先队列实现,也可以用指针实现。我偷懒用的是priority_queue
#include <bits/stdc++.h>
using namespace std;
#define lor(a,b,c) for(register int a=b;a<=c;++a)
#define ror(a,b,c) for(register int a=c;a>=b;--a)
const int N=2e5+5,INF=0x3f3f3f3f;
int n,k;
priority_queue <int,vector<int>,greater<int>> lis1,lis2,lis3;
inline void work(){
scanf("%d%d",&n,&k);
lor(i,1,n){
int t,a,b; scanf("%d%d%d",&t,&a,&b);
if(a&&b) lis3.push(t);
else if(a&&!b) lis1.push(t);
else if(!a&&b) lis2.push(t);
}
int cnt=0;
lor(i,1,k){
int f1=INF,f2=INF;
if(!lis1.empty()&&!lis2.empty()) f1=lis1.top()+lis2.top();
if(!lis3.empty()) f2=lis3.top();
if(f1==INF&&f2==INF) {puts("-1"); return;}
else if(f1<=f2) cnt+=f1,lis1.pop(),lis2.pop();
else cnt+=f2,lis3.pop();
}
printf("%d
",cnt);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
int qwq=1; while(qwq--) work();
return 0;
}
E2 Reading Books (hard version)
考场上的贪心思路是:先用(11)的书,再(01)和(10)的两本书凑对,最后从剩下的所有书中挑最小的,凑齐(m)本。
这个思路其实大体上对了,问题在于:没有枚举尽(11)的书所有的可能本数。直接贪心可能并不能准确地贪到正确的本数上。
怎么修改呢?其实也很简单:从大到小枚举可能的(11)本数,(O(1))地对选择情况做微调。思路上不存在障碍,但代码实现上出现了很多降智错误。
#include <bits/stdc++.h>
using namespace std;
#define lor(a,b,c) for(register int a=b;a<=c;++a)
#define ror(a,b,c) for(register int a=c;a>=b;--a)
typedef pair<int,int> pi;
#define fi first
#define se second
#define mp(a,b) make_pair(a,b)
const int N=2e5+5,INF=2147483647;
int n,m,k;
pi lis[4][N]; int siz[4],pos[4],L,R,ans=INF,res=0,rec[4];
inline int get(){
int t0=pos[0]<siz[0]?lis[0][pos[0]+1].fi:INF;
int t1=pos[1]<siz[1]?lis[1][pos[1]+1].fi:INF;
int t2=pos[2]<siz[2]?lis[2][pos[2]+1].fi:INF;
if(t0==t1&&t1==t2&&t2==INF) return INF;
if(t0<=t1&&t0<=t2) {++pos[0]; return t0;}
else if(t1<=t2) {++pos[1]; return t1;}
else {++pos[2]; return t2;}
}
inline int delate(int lim){
int t0=pos[0]?lis[0][pos[0]].fi:0;
int t1=pos[1]>lim?lis[1][pos[1]].fi:0;
int t2=pos[2]>lim?lis[2][pos[2]].fi:0;
if(t0==t1&&t1==t2&&t2==0) return INF;
if(t0>=t1&&t0>=t2) {--pos[0]; return t0;}
else if(t1>=t2) {--pos[1]; return t1;}
else {--pos[2]; return t2;}
}
inline void updata() {if(res<ans) {ans=res; lor(i,0,3) rec[i]=pos[i];}}
inline void report() {printf("%d
",ans); lor(j,0,3) lor(i,1,rec[j]) printf("%d ",lis[j][i].se); puts("");}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
scanf("%d%d%d",&n,&m,&k);
lor(i,1,n){
int t,a,b; scanf("%d%d%d",&t,&a,&b); int ind=(a<<1)|b;
lis[ind][++siz[ind]]=mp(t,i);
}
lor(i,0,3) sort(lis[i]+1,lis[i]+1+siz[i]);
L=max(max(max(0,2*k-m),k-siz[1]),max(k-siz[2],m-siz[0]-siz[1]-siz[2])); R=siz[3];
if(L>R) return puts("-1"),0;
lor(i,1,R) res+=lis[3][i].fi; pos[3]=R; lor(j,1,2) {lor(i,1,k-R) res+=lis[j][i].fi; pos[j]=k-R;}
lor(i,k+k-R+1,m) res+=get(); updata();
ror(i,L,R-1){
int cnt=1; res-=lis[3][pos[3]--].fi;
lor(j,1,2) if(pos[j]<k-i) res+=lis[j][++pos[j]].fi,--cnt;
if(cnt==1) res+=get(); else if(cnt==-1) res-=delate(k-i); updata();
}
report();
return 0;
}
F Cyclic Shifts Sorting
先尝试强化一下条件:如果给定的序列是一个排列怎么做?
观察发现:“转换”无法更改逆序对的奇偶性。当为奇数时一定无解;当为偶数时,通过构造性证明其有解。
找到第一小,向前滚动,若不慎落在第二格,则两次“转换”[1,3];接着找第二小,向前咕噜咕噜...;最后剩下的两个根据逆序对的奇偶性,一定是已排好序的。
回到原问题:如果是序列呢?
尝试按序列的大小关系,为序列对应一个相应的全排列。如果存在两个数大小一致,那么通过对换一定能使逆序对数的奇偶性调整到偶数;如果不存在的话..那不就和排列做法一模一样了嘛。
#include <bits/stdc++.h>
using namespace std;
#define lor(a,b,c) for(register int a=b;a<=c;++a)
#define ror(a,b,c) for(register int a=c;a>=b;--a)
typedef pair<int,int> pi;
#define fi first
#define se second
#define mp(a,b) make_pair(a,b)
const int N=505;
int n,a[N],c[N]; pi b[N];
int siz,lis[N*N];
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T> inline T read(){
#define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
char tmp=gc(); T sum=0;
while(tmp<‘0‘||tmp>‘9‘) tmp=gc();
while(tmp>=‘0‘&&tmp<=‘9‘) sum=(sum<<1)+(sum<<3)+tmp-‘0‘,tmp=gc();
return sum;
}
inline int op(int p) {lis[++siz]=p; swap(c[p],c[p+2]); swap(c[p+1],c[p+2]);}
inline void work(){
n=read<int>(); lor(i,1,n) a[i]=read<int>(),b[i]=mp(a[i],i); sort(b+1,b+1+n);
lor(i,1,n) c[b[i].se]=i;
int cnt=0; lor(i,1,n) lor(j,1,i-1) if(c[j]>c[i]) ++cnt;
if(cnt&1){
bool flag=false;
lor(i,1,n-1) if(b[i].fi==b[i+1].fi) {swap(c[b[i].se],c[b[i+1].se]); flag=true; break;}
if(!flag) {puts("-1"); return;}
}
siz=0;
lor(i,1,n-2){
int minn=n+5,pos; lor(j,i,n) if(c[j]<minn) minn=c[j],pos=j;
while(pos>i+1) op(pos-2),pos-=2;
if(pos==i+1) op(i),op(i);
}
printf("%d
",siz); lor(i,1,siz) printf("%d ",lis[i]); puts("");
}
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
int qwq=1; qwq=read<int>(); while(qwq--) work();
return 0;
}
后记
诶,还是太菜了,打场div3还被教训了一顿...剩下的时间,你小子可得出质量啊!
以上是关于Codeforces Round #653 (Div. 3)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #653 (Div. 3)ABCDE1
Codeforces Round #653 (Div. 3)D. Zero Remainder Array
Codeforces Round #653 (Div. 3) B. Multiply by 2, divide by 6 (数学)
Codeforces Round #436 E. Fire(背包dp+输出路径)