Educational Codeforces Round 76 (Rated for Div. 2)
A. Two Rival Students (CF 1257 A)
题目大意
有个学生,给定两个学生的初始站位,可以交换最多次相邻学生位置,要求那两个学生相距最远,问该距离是多少?
解题思路
移到边边就好了。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int kase; read(kase); for (int i = 1; i <= kase; i++) { int n,a,x,b; read(n); read(x); read(a); read(b); if (a>b) swap(a,b); int dis=abs(a-1)+abs(n-b); if (x>=dis) printf("%d\n",n-1); else printf("%d\n",b-a+x); } return 0; }
B. Magic Stick (CF 1257 B)
题目大意
给定两个数,问能否通过以下两种操作使得。
- 是偶数,则
- ,则
可以操作无限次。
解题思路
我们发现一旦,则可以越来越大,此时一定可以使得。而当时就在徘徊,或者到,这个时候再看在哪就好了。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int kase; read(kase); for (int i = 1; i <= kase; i++) { int x,y; read(x); read(y); if (x>3) puts("YES"); else if (x==1&&y!=1) puts("NO"); else if (y<4) puts("YES"); else puts("NO"); } return 0; }
C. Dominated Subarray (CF 1257 C)
题目大意
一个数组中,出现最多的那个数(只能有一个数)能统治这个数组,如果有多个数则没有数能统治。先给定一数组,问最短的有数字统治的长度的子数组(在原数组连续)是多少。
解题思路
在最短的子数组里,首尾的数字一定是相同的且这个数字出现了两次,因为如果里面有出现两次及以上的数字的话,这个子数组的长度能更短,所以就从左到右扫一遍,遇到每一个数,与这个数上一次出现的位置作差得到一个长度取最小值即可。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int kase; read(kase); for (int i = 1; i <= kase; i++) { int n; read(n); int a[n+1]={0}; for(int i=1;i<=n;++i) read(a[i]); unordered_map<int,int> qwq; int ans=1e9+7; for(int i=1;i<=n;++i){ if (qwq[a[i]]==0) qwq[a[i]]=i; else{ ans=min(ans,i-qwq[a[i]]+1); qwq[a[i]]=i; } } if (ans==1e9+7) puts("-1"); else printf("%d\n",ans); } return 0; }
D. Yet Another Monster Killing Problem (CF 1257 D)
题目大意
个怪兽各有一定的攻击力,现有个英雄对应的攻击力和耐力值分别为和。先派英雄依次打败这个怪兽,如果怪兽的攻击力大于所派英雄攻击力则英雄撤退回来,或者英雄的耐力值为也回来,或者中途撤退回来。英雄每打败一只怪兽其耐力值就减一。问最少派多少次英雄才能打完全部怪兽。一个英雄可以派任意多次。如果不能打完所有怪兽输出。
解题思路
注意到可以中途撤退,那么我们维护一个数组,表示能打次怪兽的英雄的最大攻击力,然后每次贪心看最多能打多少个怪兽即可。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int kase; read(kase); for (int i = 1; i <= kase; i++) { int n; read(n); int dps[n+1]; memset(dps,0,sizeof(dps)); int max_dps=0; for(int i=1;i<=n;++i) read(dps[i]),max_dps=max(dps[i],max_dps); int m; read(m); int ins[n+1]; memset(ins,0,sizeof(ins)); int max_ins=0; for(int u,v,i=1;i<=m;++i){ read(u); read(v); max_ins=max(max_ins,u); ins[v]=max(u,ins[v]); } if (max_ins<max_dps) {puts("-1"); continue;} for(int i=n-1;i>=1;--i) ins[i]=max(ins[i],ins[i+1]); int ans=0; int id=1; while(id<=n){ int qwq=dps[id]; int cnt=1; while(qwq<=ins[cnt]&&id<=n){ ++id; qwq=max(qwq,dps[id]); cnt++; } ++ans; } write(ans,'\n'); } return 0; }
E. The Contest (CF 1257 E)
题目大意
三组数,第组有个数,分别是。所有数各不相同且。现在要求第一组里的数是,第二组里的数是,第三组里的数是~,任意,甚至可以有一组或者两组里没有数。现在可以进行一种操作,即从一组数中取一个数放到另一组。问最小操作的次数。
解题思路
我们设表示数字在第几组,然后我们枚举第一组的个数,考虑最小的操作次数。
当第一组的个数为,那么数字都必须在第一组里,那么第一组要满足要求所产生的操作数就是中非的个数以及中的个数,对于第三组,我们假设有都在里面,那么第三组产生的贡献就是中的个数以及中的个数。那么我们设表示非的个数,表示中的个数,表示中的个数,表示中的个数。那么。关于的无关,储存最小值即可转移。时间复杂度。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { int k1,k2,k3; read(k1); read(k2); read(k3); int n=k1+k2+k3; int pos[n+1]; memset(pos,0,sizeof(pos)); for(int u,i=1;i<=k1;++i){ read(u); pos[u]=1; } for(int u,i=1;i<=k2;++i){ read(u); pos[u]=2; } for(int u,i=1;i<=k3;++i){ read(u); pos[u]=3; } int cnt1[n+2],ncnt1[n+2],cnt2[n+2],cnt3[n+2]; memset(cnt1,0,sizeof(cnt1)); memset(ncnt1,0,sizeof(ncnt1)); memset(cnt2,0,sizeof(cnt2)); memset(cnt3,0,sizeof(cnt3)); for(int i=1;i<=n;++i){ ncnt1[i]=ncnt1[i-1]+(pos[i]!=1); cnt3[i]=cnt3[i-1]+(pos[i]==3); } for(int i=n;i>=1;--i){ cnt1[i]=cnt1[i+1]+(pos[i]==1); cnt2[i]=cnt2[i+1]+(pos[i]==2); } int ans=1e9+7; int qwq=cnt2[n+1]+cnt3[n]; for(int i=n;i>=0;--i){ ans=min(ans,ncnt1[i]+cnt1[i+1]+qwq-cnt3[i]); if (i!=0) qwq=min(qwq,cnt2[i]+cnt3[i-1]); } write(ans,'\n'); return 0; }
F. Make Them Similar (CF 1257 F)
题目大意
个数,要求选一个数与它们异或,使得异或后的数在二进制下都有相同个数的。如果不存在这样的输出。
解题思路
由于,在二进制下,各位互不干扰,我们可以枚举前位的情况分别与这个数异或,得到的个数,第个数设为,然后再枚举后位的情况分别异或,得到的个数,第个数设为,看看是否存在一个方案使得两个位对的个数的和相等,即满足,移项得。对于我们设,把数组或者用或者丢到里,对于我们设,当得到一组时去找有没有和它相等的即可。时间复杂度。
神奇的代码
#include <bits/stdc++.h> #define MIN(a,b) ((((a)<(b)?(a):(b)))) #define MAX(a,b) ((((a)>(b)?(a):(b)))) #define ABS(a) ((((a)>0?(a):-(a)))) using namespace std; typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<PII> VPII; typedef vector<LL> VL; typedef pair<LL,LL> PLL; typedef vector<PLL> VPLL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } const int N=106; int n,ans; int a[N],cnt[N]; int tmp; struct data{ array<int,102> aa; int ans; bool operator<(const data &a)const{ return aa<a.aa; } }; set<data> qwq; int cout1(int x){ if (x==0) return 0; else return cout1(x>>1)+(x&1); } void DFS1(int x){ memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;++i) cnt[i]=cout1((a[i]&tmp)^x); data qaq; qaq.aa.fill(0); for(int i=0;i<n-1;++i) qaq.aa[i]=cnt[i+2]-cnt[1]; qaq.ans=x; qwq.insert(qaq); } void DFS2(int x){ memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;++i) cnt[i]=cout1((a[i]>>15<<15)^x); data qaq; qaq.aa.fill(0); for(int i=0;i<n-1;++i) qaq.aa[i]=cnt[1]-cnt[i+2]; qaq.ans=0; auto it=qwq.find(qaq); if (it!=qwq.end()) ans=x^((*it).ans); } int main(void) { for(int i=0;i<15;++i) tmp|=(1<<i); read(n); ans=-1; for(int i=1;i<=n;++i) read(a[i]); int len=(1<<15); for(int i=0;i<len;++i){ if (ans!=-1) break; DFS1(i); } for(int i=1;i<len;++i){ if (ans!=-1) break; DFS2((i<<15)); } if (ans==-1) puts("-1"); else printf("%d\n",ans); return 0; }
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/12288422.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步