【题解】Codeforces 1063:Round #516 (Div. 1, by Moscow Team Olympiad) ABC

总结

  1. 字符串排序后的回文子串数最多,为 Σ N x ( N x + 1 ) / 2 \Sigma N_x(Nx+1)/2 ΣNx(Nx+1)/2
  2. 01bfs学习笔记
  3. bfs获得下一步状态时,选择遍历常数数组与分别枚举中适合的方案。

A. Oh Those Palindromes 回文串,结论

给定一个非空字符串,求它的一个重排,使得回文子串的数量最多。

结论:排序。

证明:每个回文串的第一个与最后一个字符是相同的,如果字符串中字符x出现了 N x N_x Nx次,那么总的回文子串个数必然小于等于 Σ N x ( N x + 1 ) / 2 \Sigma N_x(Nx+1)/2 ΣNx(Nx+1)/2,而排序后的答案恰为这个值。

B. Labyrinth 01bfs

给定n*m(2000,2000)有空格与障碍的网格地图,初始时在给定的某空格位置上,最多向左走x步,向右走y步,上下不限,问几个格子是可达的?

拿queue去bfs会WA,拿priority_queue去bfs会TLE,注意到走一步的花费要么为1(左右),要么为0(上下),所以可以拿deque去bfs,即01bfs。
补完这套去训练一下01bfs。。

还有一个写码问题:当bfs的方向区分不大时,可以预制const数组。如果每个方向都有区分,最好分开写if或者switch。

/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 2048, MOD = 1000000007;
int n,m,sx,sy,l0,r0;
struct Node
{
	Node(int _x,int _y,int _l,int _r):x(_x),y(_y),l(_l),r(_r){}
	int x,y,l,r;
};
deque<Node> dq;
char mp[M][M], vis[M][M];
inline void go(int x,int y,int l,int r,int t)
{
	if(mp[x][y]=='.' && vis[x][y]==0 && l<=l0 && r<=r0)
	{
		vis[x][y] = 1;
		if(t) dq.emplace_back(x,y,l,r);
		else dq.emplace_front(x,y,l,r);
	}
}
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&l0,&r0);
	for(int i=1;i<=n;++i)
		scanf("%s",mp[i]+1);
	vis[sx][sy] = 1;
	dq.emplace_front(sx,sy,0,0);
	int ans = 0;
	for(Node p=dq.front();!dq.empty();++ans)
	{
		p = dq.front(); dq.pop_front();
		go(p.x+1,p.y,p.l,p.r,0);
		go(p.x-1,p.y,p.l,p.r,0);
		go(p.x,p.y+1,p.l,p.r+1,1);
		go(p.x,p.y-1,p.l+1,p.r,1);
	}
	printf("%d\n",ans );
    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

C. Dwarves, Hats and Extrasensory Abilities 交互,二分

给出n(30),在1e9*1e9的坐标平面上,每次提交一个坐标,会得到一个字符串表示这个坐标上的点的颜色(黑白),确定n个点的颜色后,两点式输出一条直线将黑点与白点分开。

时刻保证左右颜色不同并记录左右颜色的边界,输出边界中间的点,然后根据颜色更新边界。
可以做一条斜率为1e9的线来穿过差为1的两个边界。

/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 500016, MOD = 1000000007;

int save[M];
int main(void)
{
	#ifdef _LITTLEFALL_
	//freopen("in.txt","r",stdin);
    #endif

	int n = read()-1;
	char tmp[20];

	cout << 0 <<" "<< MOD/2 << endl;
	scanf("%s",tmp);	
	int ori = tmp[0]=='w' ? 1:0; //白1黑0

	int lef = 0, rig = 1000000000;
	while(n--)
	{
		int mid = (lef + rig)>>1;
		cout << mid <<" "<< MOD/2 << endl;
		scanf("%s",tmp);
		int tt = tmp[0]=='w' ? 1:0;
		if(tt==ori) lef = mid;
		else rig = mid;
	}
	printf("%d %d %d %d\n",lef,0,rig,1000000000 );

    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

D. Candies for Children 分类,枚举+check

n个人围成一圈从1到n编号,k个糖果,顺时针轮流拿糖果,糖果盒递给编号l的人,编号为r的人拿走了最后的糖果。不爱吃甜食的人或者糖果盒里只有一颗糖果时会拿一颗,其他爱吃甜食的人会拿两颗。问最多有几个爱吃甜食人,无解时输出-1.

等题解出来再补~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值