2020-02-09 19:44阅读: 151评论: 0推荐: 0

Educational Codeforces Round 76 (Rated for Div. 2)

A. Two Rival Students (CF 1257 A)

题目大意

n个学生,给定两个学生的初始站位,可以交换最多k次相邻学生位置,要求那两个学生相距最远,问该距离是多少?

解题思路

移到边边就好了。

神奇的代码
#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)

题目大意

给定两个数x,y,问能否通过以下两种操作使得x=y

  • x是偶数,则x=3x2
  • x>1,则x=x1

可以操作无限次。

解题思路

我们发现一旦x>3,则x可以越来越大,此时一定可以使得x=y。而当x=2x就在2,3徘徊,或者到1,这个时候再看y在哪就好了。

神奇的代码
#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)

题目大意

一个数组中,出现最多的那个数(只能有一个数)能统治这个数组,如果有多个数则没有数能统治。先给定一数组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;
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)

题目大意

n个怪兽各有一定的攻击力ai,现有m个英雄对应的攻击力和耐力值分别为pisi。先派英雄依次打败这n个怪兽,如果怪兽的攻击力大于所派英雄攻击力则英雄撤退回来,或者英雄的耐力值为0也回来,或者中途撤退回来。英雄每打败一只怪兽其耐力值就减一。问最少派多少次英雄才能打完全部怪兽。一个英雄可以派任意多次。如果不能打完所有怪兽输出1

解题思路

注意到可以中途撤退,那么我们维护一个数组ins[i]=maxsji(pj),表示能打i次怪兽的英雄的最大攻击力,然后每次贪心看最多能打多少个怪兽即可。

神奇的代码
#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)

题目大意

三组数,第i组有ki个数,分别是kij。所有数各不相同且1kijn。现在要求第一组里的数是1q,第二组里的数是q+1p,第三组里的数是p+1~nq,p任意,甚至可以有一组或者两组里没有数。现在可以进行一种操作,即从一组数中取一个数放到另一组。问最小操作的次数。

解题思路

我们设pos[i]表示数字i在第几组,然后我们枚举第一组的个数,考虑最小的操作次数。
当第一组的个数为l,那么数字1l都必须在第一组里,那么第一组要满足要求所产生的操作数就是pos[1..l]中非1的个数以及pos[l+1..n]1的个数,对于第三组,我们假设有pn都在里面,那么第三组产生的贡献就是pos[p..n]2的个数以及pos[l+1..p1]3的个数。那么我们设ncnt1[i]表示pos[1..i]1的个数,cnt1[i]表示pos[i..n]1的个数,cnt2[i]表示pos[i..n]2的个数,cnt3[i]表示pos[1..i]3的个数。那么dp[l]=minp>l(ncnt1[l]+cnt1[l+1]+cnt2[p]+cnt3[p1]cnt3[l])。关于pl无关,储存最小值即可O(1)转移。时间复杂度O(n)

神奇的代码
#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)

题目大意

n个数,要求选一个数x与它们异或,使得异或后的数在二进制下都有相同个数的1。如果不存在这样的x输出1

解题思路

由于x2301,在二进制下,各位互不干扰,我们可以枚举前15位的情况分别与这n个数异或,得到1的个数,第i个数设为li,然后再枚举后15位的情况分别异或,得到1的个数,第i个数设为ri,看看是否存在一个方案使得两个15位对1的个数的和相等,即满足i,j[1,n],li+ri=lj+rj,移项得ljli=rirj。对于li我们设cli=lil1,把cli数组Hash或者用map或者丢到set里,对于ri我们设cri=r1ri,当得到一组cri时去找有没有和它相等的cli即可。时间复杂度O(n220)

神奇的代码
#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 中国大陆许可协议进行许可。

posted @   ~Lanly~  阅读(151)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.