并不对劲的CF1349B&C:Game of Median Life

Posted xzyf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并不对劲的CF1349B&C:Game of Median Life相关的知识,希望对你有一定的参考价值。

CF1349B Orac and Medians

题目描述

(n)个数,(a_1,a_2,...,a_n)
该题中(m)个数的中位数的定义是:将这(m)个数排序后,排在第(lfloor frac{m+1}{2} floor)的数。
可以进行的操作是:选一个区间([l,r]),将(a_l,a_{l+1},...,a_r)都变成(a_l,a_{l+1},...,a_r)的中位数。
给出(a_1,...,a_n)(k),问能否把所有数都变成(k)
(nleq 10^5;a_1,...,a_n,kleq 10^9)

一行题解

存在长度不少于2且区间内大于等于(k)的数的个数多于小于(k)的数的个数的区间。

题解

首先,如果(k)(a_1,...,a_n)中没出现过,就肯定不行;如果只有一个数而且和(k)相等,就肯定行。
一次“操作”可以把相邻两个数都变为它们之中较小的那个(称为“第一招”),也可以把有两个数相等的相邻的三个数变成那两个数的值(称为“第二招”)。
对于区间([l,r](l<r)),如果区间中位数大于等于(k)
(1)(a_l,...,a_r)中没有(k)(k)会出现在(l)左侧或(r)右侧,一次操作把(a_l,...,a_r)都变成大于(k)的数,用“第二招”可以使与(k)相邻的地方出现多个比(k)大的数,再用“第一招”可以把这些大于(k)的数都变成(k),再用“第二招”把所有数都变成(k)
(2)(a_l,...,a_r)中有(k):如果这些数的中位数就是(k),直接把它们变成(k),再用“第二招”把所有数变成(k);如果中位数大于(k),会发现(k)的某一侧的中位数也是大于等于(k),就和(1)相同。
所以“存在一个长度不少于2的区间中位数大于等于(k)”是“能把所有数变成(k)”的充分条件。
当不存在不少于2的区间中位数大于等于(k)时,任何一个区间的中位数都小于(k),所以任何操作都只会把一些数变成小于(k)的数,不能把所有数变成(k)。所以“存在一个长度不少于2的区间中位数大于等于(k)”是“能把所有数变成(k)”的必要条件。
所以判断“存在一个长度不少于2的区间中位数大于等于(k)”就行。
“区间中位数大于等于(k)”等价于“区间大于等于(k)的数多于小于(k)的数”,等价于“区间大于等于(k)的数的个数减小于(k)的数的个数大于0”。
把“大于等于(k)的数”看成1,“小于(k)的数”看成-1,判断前缀和的正负。

代码

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 100007
using namespace std;
int read()
{
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!=‘-‘)ch=getchar();
	if(ch==‘-‘)f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar();
	return x*f;
}
void write(int x)
{
	char ch[20];int f=0;
	if(!x){putchar(‘0‘),putchar(‘
‘);return;}
	if(x<0)putchar(‘-‘),x=-x;
	while(x)ch[++f]=x%10+‘0‘,x/=10;
	while(f)putchar(ch[f--]);
	putchar(‘
‘);
}
int t,n,k,a[maxn],b[maxn];
int main()
{
	t=read();
	while(t--)
	{
		n=read(),k=read();int jud1=0;
		rep(i,1,n){a[i]=read();if(a[i]==k)jud1=1;}
		if(!jud1){puts("no");continue;}
		if(n==1){puts("yes");continue;}
		rep(i,1,n){if(a[i]>=k)b[i]=1;else b[i]=-1;}
		rep(i,1,n)b[i]+=b[i-1];
		int mn=0;jud1=0;
		rep(i,2,n)
		{
			mn=min(mn,b[i-2]);
			if(b[i]-mn>0){jud1=1;break;}
		}
		puts(jud1?"yes":"no");
	}
	return (~(0-0)+1);
}

CF1349C Orac and Game of Life

题目描述

有一个(n imes m)的网格,每个格有一个0或1的数。
“好”的格的定义为:该格正上、正下、正左、正右与它相邻的格上的数都与它不同。
每操作一次,会把所有“好”的格上的数异或1,不是“好”的格上的数不变。
(t)组询问,每次给出(x,y,k),问(k)次操作后在((x,y))格上的数。
(n,mleq 1000;tleq 10^5)

题解

对于一个“好”的格,它旁边的那个跟它数一样的格在操作后会跟它一起变,所以“好”的格一直都是“好”的。
对于一个不“好”的格,如果有一个与它相邻的格子是“好”的,那么这次操作它不会变,与它相邻的“好”格子会变,它们在这场操作后数相同,原来不“好”的格会变成“好”格。
所以,对于“好”格,(k)次操作后格上的数会异或上(k)个1;对于不“好”格,(k)小于它到离它最近的“好”格的距离它的数就不变,(k)大于等于它到离它最近的“好”格的距离它就异或上(k-距离)个1。

代码

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define LL long long
#define rep(i,x,y) for(int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define maxn 1007 
using namespace std;
LL read()
{
	LL x=0,f=1;char ch=getchar();
	while(!isdigit(ch)&&ch!=‘-‘)ch=getchar();
	if(ch==‘-‘)f=-1,ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-‘0‘,ch=getchar();
	return x*f;
}
void write(int x)
{
	char ch[20];int f=0;
	if(!x){putchar(‘0‘),putchar(‘
‘);return;}
	if(x<0)putchar(‘-‘),x=-x;
	while(x)ch[++f]=x%10+‘0‘,x/=10;
	while(f)putchar(ch[f--]);
	putchar(‘
‘);
}
int n,m,t,dis[maxn][maxn],qx[maxn*maxn],qy[maxn*maxn],hd,tl;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
char s[maxn][maxn];
inline int in(int x,int y){if(1<=x&&x<=n&&1<=y&&y<=m)return 1;return 0;} 
int main()
{
	n=read(),m=read(),t=read();hd=1;
	rep(i,1,n){scanf("%s",s[i]+1);}
	rep(i,1,n)rep(j,1,m)
	{
		int yes=0;
		rep(k,0,3)
		{
			int nx=i+dx[k],ny=j+dy[k];
			if(in(nx,ny)&&s[nx][ny]==s[i][j]){yes=1;break;}
		}
		if(yes)++tl,qx[tl]=i,qy[tl]=j;
		else dis[i][j]=-1;
	}
	while(hd<=tl)
	{
		int ux=qx[hd],uy=qy[hd];hd++;
		rep(k,0,3)
		{
			int nx=ux+dx[k],ny=uy+dy[k];
			if(in(nx,ny)&&dis[nx][ny]==-1){dis[nx][ny]=dis[ux][uy]+1,tl++,qx[tl]=nx,qy[tl]=ny;} 
		}
	}
	if(tl){rep(i,1,n)rep(j,1,m)if(dis[i][j]==-1)return 0;}
	while(t--)
	{
		int x=read(),y=read();LL k=read();
		if(!tl||k<(LL)dis[x][y])putchar(s[x][y]),putchar(‘
‘); 
		else write((s[x][y]-‘0‘)^((k-(LL)dis[x][y])&1ll));
	}
	return (~(0-0)+1);
}

一些感想

小号也能打div1啦!
想做个拿猎虫打龙蚀虫的视频。





















以上是关于并不对劲的CF1349B&C:Game of Median Life的主要内容,如果未能解决你的问题,请参考以下文章

并不对劲的CF1239B&C&D Programming Task in the Train to Catowice City

并不对劲的复健训练-CF1187D

并不对劲的CF1245E&F:Cleaning Ladders

并不对劲的CF480E:Parking Lot

并不对劲的后缀数组

并不对劲的st表